verified_double 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/CHANGELOG.markdown +8 -0
  2. data/README.md +21 -49
  3. data/features/CHANGELOG.markdown +8 -0
  4. data/features/accessor_method_contracts.feature +107 -0
  5. data/features/customizing_arguments_and_return_values.feature +2 -2
  6. data/features/readme.md +21 -49
  7. data/features/rspec_mock_compatibility.feature +230 -0
  8. data/features/step_definitions/verified_double_steps.rb +17 -0
  9. data/features/{verified_double.feature → verified_mocks.feature} +5 -6
  10. data/features/verified_stubs.feature +94 -0
  11. data/lib/verified_double.rb +25 -10
  12. data/lib/verified_double/matchers.rb +35 -0
  13. data/lib/verified_double/method_signature_value.rb +15 -1
  14. data/lib/verified_double/method_signatures_report.rb +55 -0
  15. data/lib/verified_double/recording_double.rb +33 -12
  16. data/lib/verified_double/relays_to_internal_double_returning_self.rb +12 -0
  17. data/lib/verified_double/version.rb +1 -1
  18. data/spec/spec_helper.rb +3 -4
  19. data/spec/unit_helper.rb +3 -2
  20. data/spec/verified_double/matchers_spec.rb +96 -0
  21. data/spec/verified_double/method_signature_value_spec.rb +35 -0
  22. data/spec/verified_double/method_signatures_report_spec.rb +214 -0
  23. data/spec/verified_double/parse_method_signature_spec.rb +5 -1
  24. data/spec/verified_double/recording_double_spec.rb +103 -30
  25. data/spec/verified_double_spec.rb +70 -7
  26. data/verified_double.gemspec +0 -2
  27. metadata +17 -38
  28. data/lib/verified_double/get_registered_signatures.rb +0 -11
  29. data/lib/verified_double/get_unverified_signatures.rb +0 -13
  30. data/lib/verified_double/get_verified_signatures.rb +0 -17
  31. data/lib/verified_double/output_unverified_signatures.rb +0 -18
  32. data/lib/verified_double/report_unverified_signatures.rb +0 -16
  33. data/lib/verified_double/verify_doubles_service.rb +0 -15
  34. data/spec/verified_double/get_registered_signatures_spec.rb +0 -42
  35. data/spec/verified_double/get_unverified_signatures_spec.rb +0 -52
  36. data/spec/verified_double/get_verified_signatures_spec.rb +0 -63
  37. data/spec/verified_double/output_unverified_signatures_spec.rb +0 -58
  38. data/spec/verified_double/report_unverified_signatures_spec.rb +0 -57
  39. data/spec/verified_double/verify_doubles_service_spec.rb +0 -24
@@ -1,6 +1,5 @@
1
1
  require 'active_support/core_ext/string'
2
2
  require 'pry'
3
- require 'rspec/fire'
4
3
 
5
4
  require 'verified_double/boolean'
6
5
 
@@ -10,6 +9,8 @@ require 'verified_double/boolean'
10
9
  require "verified_double/method_signature"
11
10
  require "verified_double/method_signature_value"
12
11
 
12
+ # Requiring because these are macros.
13
+ require 'verified_double/relays_to_internal_double_returning_self'
14
+
13
15
  RSpec.configure do |config|
14
- config.include(RSpec::Fire)
15
16
  end
@@ -0,0 +1,96 @@
1
+ require 'unit_helper'
2
+ require 'verified_double/matchers'
3
+
4
+ describe VerifiedDouble::Matchers do
5
+ include VerifiedDouble::Matchers
6
+
7
+ describe "#verify_accessor_contract(contract)" do
8
+ class Collaborator
9
+ attr_accessor :value
10
+ end
11
+
12
+ let(:contract) { 'Collaborator#value()=>String' }
13
+
14
+ subject { Collaborator.new }
15
+
16
+ it "adds the method signature to the verified signatures from matchers" do
17
+ expect(subject).to verify_accessor_contract(contract)
18
+ expect(VerifiedDouble.verified_signatures_from_matchers.last.to_s).to eq(contract)
19
+ end
20
+
21
+ context "where the contract has multiple return values" do
22
+ let(:contract) { 'Collaborator#value=>String,Integer' }
23
+
24
+ it "complains that the matcher expects only one return value" do
25
+ expect { expect(subject).to verify_accessor_contract(contract) }
26
+ .to raise_error(described_class::CannotHandleMultipleReturnValues)
27
+ end
28
+ end
29
+
30
+ context "where the contract return value can be initialized" do
31
+ let(:contract) { 'Collaborator#value=>String' }
32
+
33
+ it "assigns the initialized value to the subject's writer and compares it to the subject's reader" do
34
+ expect(subject.value).to be_nil
35
+
36
+ expect(subject).to verify_accessor_contract(contract)
37
+ expect(subject.value).to eq(String.new)
38
+ end
39
+ end
40
+
41
+ context "where the contract return value is a class which cannot be initialized" do
42
+ let(:contract) { 'Collaborator#value=>Integer' }
43
+
44
+ it "assigns the a new object to the subject's writer and compares it to the subject's reader" do
45
+ expect(subject.value).to be_nil
46
+
47
+ expect(subject).to verify_accessor_contract(contract)
48
+ expect(subject.value.class).to eq(Object)
49
+ end
50
+ end
51
+
52
+ context "where the contract return value is an instance" do
53
+ let(:contract) { 'Collaborator#value=>1' }
54
+
55
+ it "assigns the instance to the subject's writer and compares it to the subject's reader" do
56
+ expect(subject.value).to be_nil
57
+
58
+ expect(subject).to verify_accessor_contract(contract)
59
+ expect(subject.value).to eq(1)
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "#verify_reader_contract" do
65
+ class AnotherCollaborator
66
+ attr_reader :value
67
+
68
+ def initialize(value)
69
+ @value = value
70
+ end
71
+ end
72
+
73
+ let(:contract) { 'AnotherCollaborator#value()=>String' }
74
+ let(:value) { 'a string' }
75
+
76
+ subject { AnotherCollaborator.new(value) }
77
+
78
+ it "checks if the method being verified has the same class as the return value" do
79
+ expect(subject).to verify_reader_contract(contract)
80
+ end
81
+
82
+ it "adds the method signature to the verified signatures from matchers" do
83
+ expect(subject).to verify_reader_contract(contract)
84
+ expect(VerifiedDouble.verified_signatures_from_matchers.last.to_s).to eq(contract)
85
+ end
86
+
87
+ context "where the contract has multiple return values" do
88
+ let(:contract) { 'Collaborator#value=>String,Integer' }
89
+
90
+ it "complains that the matcher expects only one return value" do
91
+ expect { expect(subject).to verify_reader_contract(contract) }
92
+ .to raise_error(described_class::CannotHandleMultipleReturnValues)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -53,6 +53,15 @@ describe VerifiedDouble::MethodSignatureValue do
53
53
  describe "#modified_class" do
54
54
  subject { method_signature_value.modified_class }
55
55
 
56
+ context "where the value is recording double" do
57
+ let(:recording_double){ VerifiedDouble.of_instance('Object') }
58
+ let(:method_signature_value) { described_class.new(recording_double) }
59
+
60
+ it "is the class represented by the class_name of the recording double" do
61
+ expect(subject).to eq(Object)
62
+ end
63
+ end
64
+
56
65
  context "where the value is true" do
57
66
  let(:method_signature_value) { described_class.new(true) }
58
67
  it { expect(subject).to eq(VerifiedDouble::Boolean) }
@@ -79,4 +88,30 @@ describe VerifiedDouble::MethodSignatureValue do
79
88
  expect(subject.recommended_value.value).to_not eq(subject)
80
89
  end
81
90
  end
91
+
92
+ describe "#as_instance" do
93
+ context "where the value is an instance" do
94
+ subject { described_class.new(:some_value) }
95
+
96
+ it "returns the value" do
97
+ expect(subject.as_instance).to eq(:some_value)
98
+ end
99
+ end
100
+
101
+ context "where the value is a class which can be initialized" do
102
+ subject { described_class.new(String) }
103
+
104
+ it "returns the initialized instance of the value " do
105
+ expect(subject.as_instance).to eq(String.new)
106
+ end
107
+ end
108
+
109
+ context "where the value is a class which cannot be initialized" do
110
+ subject { described_class.new(Integer) }
111
+
112
+ it "returns an object" do
113
+ expect(subject.as_instance).to be_an(Object)
114
+ end
115
+ end
116
+ end
82
117
  end
@@ -0,0 +1,214 @@
1
+ require 'unit_helper'
2
+ require 'verified_double'
3
+ require 'verified_double/method_signatures_report'
4
+
5
+ describe VerifiedDouble::MethodSignaturesReport do
6
+ describe "initialize", verifies_contract: 'VerifiedDouble::MethodSignaturesReport.new()=>VerifiedDouble::MethodSignaturesReport' do
7
+ it { expect(described_class.new).to be_a(VerifiedDouble::MethodSignaturesReport) }
8
+ end
9
+
10
+ describe "#set_registered_signatures", verifies_contract: 'VerifiedDouble::MethodSignaturesReport#set_registered_signatures()=>VerifiedDouble::MethodSignaturesReport' do
11
+
12
+ let(:recording_double_1) {
13
+ double('VerifiedDouble::RecordingDouble',
14
+ method_signatures: [method_signature_1]) }
15
+
16
+ let(:recording_double_2) {
17
+ double('VerifiedDouble::RecordingDouble',
18
+ method_signatures: [method_signature_2]) }
19
+
20
+ let(:method_signature_1) {
21
+ VerifiedDouble::MethodSignature.new(class_name: 'Object', method_operator: '#', method: 'to_s') }
22
+
23
+ let(:method_signature_2) {
24
+ VerifiedDouble::MethodSignature.new(class_name: 'Object', method_operator: '#', method: 'inspect') }
25
+
26
+ let(:verified_double_module){ VerifiedDouble.of_class('VerifiedDouble') }
27
+
28
+ context "with multiple recording doubles in the registry" do
29
+ it "maps and flattens the method signatures of the recording doubles" do
30
+ verified_double_module
31
+ .should_receive(:registry)
32
+ .and_return([recording_double_1, recording_double_2])
33
+
34
+ expect(subject.set_registered_signatures.registered_signatures).to eq(
35
+ [method_signature_1, method_signature_2])
36
+ end
37
+ end
38
+
39
+ context "with recording doubles with duplicate signatures" do
40
+ let(:recording_double_2) {
41
+ double('VerifiedDouble::RecordingDouble',
42
+ method_signatures: [method_signature_1]) }
43
+
44
+ it "returns distinct method signatures" do
45
+ verified_double_module
46
+ .should_receive(:registry)
47
+ .and_return([recording_double_1, recording_double_2])
48
+
49
+ expect(subject.set_registered_signatures.registered_signatures).to eq([method_signature_1])
50
+ end
51
+ end
52
+ end
53
+
54
+ describe "#set_verified_signatures_from_tags", verifies_contract: 'VerifiedDouble::MethodSignaturesReport#set_verified_signatures_from_tags()=>VerifiedDouble::MethodSignaturesReport' do
55
+ let(:method_signature) { VerifiedDouble::MethodSignature.new }
56
+
57
+ let(:nested_example_group){ double(:nested_example_group) }
58
+
59
+ let(:parse_method_signature_service) {
60
+ VerifiedDouble.of_instance('VerifiedDouble::ParseMethodSignature') }
61
+
62
+ let(:parse_method_signature_service_class) {
63
+ VerifiedDouble.of_class('VerifiedDouble::ParseMethodSignature') }
64
+
65
+ let(:example_with_verified_contract_tag){
66
+ double(:example_with_verified_contract_tag,
67
+ metadata: { verifies_contract: 'signature' }) }
68
+
69
+ let(:example_without_verified_contract_tag){
70
+ double(:example_without_verified_contract_tag,
71
+ metadata: { focus: true }) }
72
+
73
+ subject { described_class.new.set_verified_signatures_from_tags(nested_example_group) }
74
+
75
+ it "filters rspec examples with the tag 'verifies_contract'" do
76
+ nested_example_group
77
+ .stub_chain(:class, :descendant_filtered_examples)
78
+ .and_return([example_with_verified_contract_tag, example_without_verified_contract_tag])
79
+
80
+ parse_method_signature_service_class
81
+ .should_receive(:new)
82
+ .with(example_with_verified_contract_tag.metadata[:verifies_contract])
83
+ .and_return(parse_method_signature_service)
84
+
85
+ parse_method_signature_service
86
+ .should_receive(:execute)
87
+ .and_return(method_signature)
88
+
89
+ expect(subject.verified_signatures_from_tags).to eq([method_signature])
90
+ end
91
+
92
+ it "returns unique signatures" do
93
+ nested_example_group
94
+ .stub_chain(:class, :descendant_filtered_examples)
95
+ .and_return([example_with_verified_contract_tag, example_with_verified_contract_tag])
96
+
97
+ parse_method_signature_service_class
98
+ .should_receive(:new)
99
+ .with(example_with_verified_contract_tag.metadata[:verifies_contract])
100
+ .at_least(:once)
101
+ .and_return(parse_method_signature_service)
102
+
103
+ parse_method_signature_service
104
+ .should_receive(:execute)
105
+ .and_return(method_signature)
106
+
107
+ expect(subject.verified_signatures_from_tags).to eq([method_signature])
108
+ end
109
+ end
110
+
111
+ describe "#identify_unverified_signatures", verifies_contract: 'VerifiedDouble::MethodSignaturesReport#identify_unverified_signatures()=>VerifiedDouble::MethodSignaturesReport' do
112
+ let(:registered_signature) {
113
+ VerifiedDouble::MethodSignature.new(
114
+ class_name: 'Person',
115
+ method: 'find',
116
+ method_operator: '.',
117
+ args: [VerifiedDouble::MethodSignatureValue.new(1)]) }
118
+
119
+ let(:registered_signature_without_match) {
120
+ VerifiedDouble::MethodSignature.new(
121
+ class_name: 'Person',
122
+ method: 'save!',
123
+ method_operator: '#') }
124
+
125
+ let(:verified_signature) {
126
+ VerifiedDouble::MethodSignature.new(
127
+ class_name: 'Person',
128
+ method: 'find',
129
+ method_operator: '.',
130
+ args: [VerifiedDouble::MethodSignatureValue.new(Object)]) }
131
+
132
+ it "retains registered signatures that cannot accept any of the verified_signatures" do
133
+ expect(registered_signature.accepts?(verified_signature)).to be_true
134
+ expect(registered_signature_without_match.accepts?(verified_signature)).to be_false
135
+
136
+ subject.registered_signatures = [registered_signature, registered_signature_without_match]
137
+ subject.verified_signatures = [verified_signature]
138
+
139
+ expect(subject.unverified_signatures).to be_empty
140
+ expect(subject.identify_unverified_signatures).to eq(subject)
141
+ expect(subject.unverified_signatures).to eq([registered_signature_without_match])
142
+ end
143
+ end
144
+
145
+ describe "#output_unverified_signatures", verifies_contract: 'VerifiedDouble::MethodSignaturesReport#output_unverified_signatures()=>VerifiedDouble::MethodSignaturesReport' do
146
+ class Dummy
147
+ end
148
+
149
+ let(:unverified_signatures){ [
150
+ VerifiedDouble::MethodSignature.new(
151
+ class_name: 'Dummy',
152
+ method_operator: '.',
153
+ method: 'find',
154
+ args: [VerifiedDouble::MethodSignatureValue.new(1)],
155
+ return_values: [VerifiedDouble::MethodSignatureValue.new(Dummy.new)]),
156
+ VerifiedDouble::MethodSignature.new(
157
+ class_name: 'Dummy',
158
+ method_operator: '.',
159
+ method: 'where',
160
+ args: [VerifiedDouble::MethodSignatureValue.new(id: 1)],
161
+ return_values: [VerifiedDouble::MethodSignatureValue.new(Dummy.new)]) ] }
162
+
163
+ context "where there are no unverified_signatures" do
164
+ it "should not output anything" do
165
+ subject.unverified_signatures = []
166
+ subject.should_not_receive(:puts)
167
+ expect(subject.output_unverified_signatures).to eq(subject)
168
+ end
169
+ end
170
+
171
+ context "where there are unverified_signatures" do
172
+ it "should output the recommended versions of the unverified_signatures" do
173
+ subject.unverified_signatures = unverified_signatures
174
+
175
+ lines = [
176
+ "The following mocks are not verified:",
177
+ unverified_signatures[0].recommended_verified_signature,
178
+ unverified_signatures[1].recommended_verified_signature ]
179
+
180
+ subject.should_receive(:puts).with(lines.join("\n"))
181
+ subject.output_unverified_signatures
182
+ end
183
+ end
184
+ end
185
+
186
+ describe "#set_verified_signatures_from_matchers", verifies_contract: 'VerifiedDouble::MethodSignaturesReport#set_verified_signatures_from_matchers()=>VerifiedDouble::MethodSignaturesReport' do
187
+ let(:verified_double_module){
188
+ VerifiedDouble.of_class('VerifiedDouble') }
189
+
190
+ let(:method_signature) { VerifiedDouble::MethodSignature.new }
191
+
192
+ it "works" do
193
+ verified_double_module
194
+ .should_receive(:verified_signatures_from_matchers)
195
+ .and_return([method_signature])
196
+
197
+ expect(subject.set_verified_signatures_from_matchers.verified_signatures_from_matchers)
198
+ .to eq([method_signature])
199
+ end
200
+ end
201
+
202
+ describe "#merge_verified_signatures", verifies_contract: 'VerifiedDouble::MethodSignaturesReport#merge_verified_signatures()=>VerifiedDouble::MethodSignaturesReport' do
203
+ let(:method_signature_from_tag) { VerifiedDouble::MethodSignature.new }
204
+ let(:method_signature_from_matcher) { VerifiedDouble::MethodSignature.new }
205
+
206
+ it "merges the verified signatures from the tags and the matchers" do
207
+ subject.verified_signatures_from_tags = [method_signature_from_tag]
208
+ subject.verified_signatures_from_matchers = [method_signature_from_matcher]
209
+
210
+ expect(subject.verified_signatures).to be_empty
211
+ expect(subject.merge_verified_signatures.verified_signatures).to eq([method_signature_from_tag, method_signature_from_matcher])
212
+ end
213
+ end
214
+ end
@@ -4,7 +4,11 @@ require 'verified_double/parse_method_signature'
4
4
  describe VerifiedDouble::ParseMethodSignature do
5
5
  subject { described_class.new(string) }
6
6
 
7
- describe "#execute" do
7
+ describe "#initialize", verifies_contract: 'VerifiedDouble::ParseMethodSignature.new(String)=>VerifiedDouble::ParseMethodSignature' do
8
+ it { expect(described_class.new("Class#method(:arg_1, :arg_2)=>:return_value")).to be_a(VerifiedDouble::ParseMethodSignature) }
9
+ end
10
+
11
+ describe "#execute", verifies_contract: 'VerifiedDouble::ParseMethodSignature#execute()=>VerifiedDouble::MethodSignature' do
8
12
  let(:string){ "Class#method(:arg_1, :arg_2)=>:return_value" }
9
13
 
10
14
  subject { described_class.new(string).execute }
@@ -5,12 +5,23 @@ describe VerifiedDouble::RecordingDouble do
5
5
  let(:class_name) { 'Object' }
6
6
  let(:internal_double) { double(class_name) }
7
7
 
8
- subject { VerifiedDouble::RecordingDouble.new(internal_double) }
8
+ subject { VerifiedDouble::RecordingDouble.new(internal_double, class_name) }
9
9
 
10
10
  describe "#initialize" do
11
11
  it "requires a double" do
12
12
  expect(subject.double).to eq(internal_double)
13
13
  end
14
+
15
+ context "with method_stubs hash" do
16
+ let(:stubbed_method){ :some_method }
17
+ let(:assumed_output){ :some_output }
18
+
19
+ subject { VerifiedDouble::RecordingDouble.new(internal_double, class_name, some_method: assumed_output) }
20
+
21
+ it "stubs the methods of the instance" do
22
+ expect(subject.send(stubbed_method)).to eq(assumed_output)
23
+ end
24
+ end
14
25
  end
15
26
 
16
27
  it "delegates all unknown calls to its internal double" do
@@ -24,14 +35,14 @@ describe VerifiedDouble::RecordingDouble do
24
35
 
25
36
  context "where the internal double is a class" do
26
37
  let(:class_name) { 'Dummy' }
27
- let(:internal_double) { fire_class_double(class_name).as_replaced_constant }
38
+ let(:internal_double) { stub_const(class_name, Class.new) }
28
39
 
29
40
  it { expect(subject.to_s).to eq("VerifiedDouble.of_class('#{class_name}')") }
30
41
  end
31
42
 
32
43
  context "where the internal double is an instance" do
33
44
  let(:class_name) { 'Dummy' }
34
- let(:internal_double) { fire_double(class_name) }
45
+ let(:internal_double) { double(class_name) }
35
46
 
36
47
  it { expect(subject.to_s).to eq("VerifiedDouble.of_instance('#{class_name}')") }
37
48
  end
@@ -44,42 +55,42 @@ describe VerifiedDouble::RecordingDouble do
44
55
  end
45
56
 
46
57
  describe "#class_name" do
47
- context "where the internal double is an RSpec::Fire::FireObjectDouble" do
48
- it "is the name of the class represented by the FireObjectDouble" do
49
- internal_double = fire_double('Object')
50
- subject = described_class.new(internal_double)
58
+ context "where the internal double is a double" do
59
+ it "is the name of the class represented by the double" do
60
+ internal_double = double('Object')
61
+ subject = described_class.new(internal_double, 'Object')
51
62
  expect(subject.class_name).to eq('Object')
52
63
  end
53
64
  end
54
65
 
55
- context "where the internal double is an rspec fire class double" do
56
- it "is the name of the class represented by the rspec fire class double" do
57
- internal_double = fire_class_double('Object').as_replaced_constant
58
- subject = described_class.new(internal_double)
66
+ context "where the internal double is a stub const" do
67
+ it "is the name of the class represented by the class double" do
68
+ internal_double = stub_const('Object', Class.new)
69
+ subject = described_class.new(internal_double, 'Object')
59
70
  expect(subject.class_name).to eq('Object')
60
71
  end
61
72
  end
62
73
  end
63
74
 
64
75
  describe "#class_double?" do
65
- it "should be true if the internal double is an rspec fire class double" do
66
- internal_double = fire_double('Object')
67
- subject = described_class.new(internal_double)
76
+ it "should be true if the internal double is a class double" do
77
+ internal_double = double('Object')
78
+ subject = described_class.new(internal_double, 'Object')
68
79
  expect(subject).to_not be_class_double
69
80
  end
70
81
 
71
- it "should be false if the internal double is not an rspec fire class double" do
72
- internal_double = fire_class_double('Object').as_replaced_constant
73
- subject = described_class.new(internal_double)
82
+ it "should be false if the internal double is not an class double" do
83
+ internal_double = stub_const('Object', Class.new)
84
+ subject = described_class.new(internal_double, 'Object')
74
85
  expect(subject).to be_class_double
75
86
  end
76
87
  end
77
88
 
78
89
  describe "#method_operator" do
79
90
  context "when the subject wraps an instance double" do
80
- let(:internal_double) { fire_double('Object') }
91
+ let(:internal_double) { double(class_name) }
81
92
 
82
- subject { VerifiedDouble::RecordingDouble.new(internal_double) }
93
+ subject { VerifiedDouble::RecordingDouble.new(internal_double, class_name) }
83
94
 
84
95
  it "is #" do
85
96
  expect(subject.method_operator).to eq("#")
@@ -87,9 +98,9 @@ describe VerifiedDouble::RecordingDouble do
87
98
  end
88
99
 
89
100
  context "when the subject wraps a class double" do
90
- let(:internal_double) { fire_class_double('Object') }
101
+ let(:internal_double) { stub_const(class_name, Class.new) }
91
102
 
92
- subject { VerifiedDouble::RecordingDouble.new(internal_double) }
103
+ subject { VerifiedDouble::RecordingDouble.new(internal_double, class_name) }
93
104
 
94
105
  it "is '.'" do
95
106
  expect(subject.method_operator).to eq(".")
@@ -101,37 +112,99 @@ describe VerifiedDouble::RecordingDouble do
101
112
  it "appends a new method signature with the method to the recording double's method signatures" do
102
113
  expect(subject.method_signatures).to be_empty
103
114
 
104
- subject.should_receive(:to_s)
105
- subject.should_receive(:inspect)
115
+ subject.should_receive(:fake_to_s)
116
+ subject.should_receive(:fake_inspect)
106
117
 
107
- expect(subject.method_signatures.map(&:method)).to eq(['to_s', 'inspect'])
118
+ expect(subject.method_signatures.map(&:method)).to eq(['fake_to_s', 'fake_inspect'])
108
119
 
109
- subject.to_s
110
- subject.inspect
120
+ subject.fake_to_s
121
+ subject.fake_inspect
122
+ end
123
+ end
124
+
125
+ describe "#stub(method)" do
126
+ it "appends a new method signature with the method to the recording double's method signatures" do
127
+ expect(subject.method_signatures).to be_empty
128
+
129
+ subject.stub(:fake_to_s)
130
+ subject.stub(:fake_inspect)
131
+
132
+ expect(subject.method_signatures.map(&:method)).to eq(['fake_to_s', 'fake_inspect'])
111
133
  end
112
134
  end
113
135
 
114
136
  describe "#with(*args)" do
115
137
  it "sets the args of the last method signature" do
116
- subject.should_receive(:to_s).with(:arg_1, :arg_2)
138
+ subject.should_receive(:fake_to_s).with(:arg_1, :arg_2)
117
139
 
118
140
  expect(subject.method_signatures[0].args).to be_all{|arg| arg.is_a?(VerifiedDouble::MethodSignatureValue) }
119
141
  expect(subject.method_signatures[0].args.map(&:value)).to eq([:arg_1, :arg_2])
120
142
 
121
- subject.to_s(:arg_1, :arg_2)
143
+ subject.fake_to_s(:arg_1, :arg_2)
122
144
  end
123
145
  end
124
146
 
125
147
  describe "#and_return(return_value)" do
126
148
  it "sets the return value of the last method signature" do
127
- subject.should_receive(:to_s).with(:arg_1, :arg_2).and_return(:return_value)
149
+ subject.should_receive(:fake_to_s).with(:arg_1, :arg_2).and_return(:return_value)
128
150
 
129
151
  return_values = subject.method_signatures[0].return_values
130
152
  expect(return_values).to have(1).return_value
131
153
  expect(return_values.first).to be_a(VerifiedDouble::MethodSignatureValue)
132
154
  expect(return_values.first.value).to eq(:return_value)
133
155
 
134
- subject.to_s(:arg_1, :arg_2)
156
+ subject.fake_to_s(:arg_1, :arg_2)
157
+ end
158
+ end
159
+
160
+ describe "#once" do
161
+ it "is relayed to the internal double and returns the recording double" do
162
+ expect(subject.should_receive(:fake_to_s).once).to be_a(described_class)
163
+ subject.fake_to_s
164
+ end
165
+ end
166
+
167
+ describe "#twice" do
168
+ it "is relayed to the internal double and returns the recording double" do
169
+ expect(subject.should_receive(:fake_to_s).twice).to be_a(described_class)
170
+ subject.fake_to_s
171
+ subject.fake_to_s
172
+ end
173
+ end
174
+
175
+ describe "#at_least" do
176
+ it "is relayed to the internal double and returns the recording double" do
177
+ expect(subject.should_receive(:fake_to_s).at_least(:once)).to be_a(described_class)
178
+ subject.fake_to_s
179
+ end
180
+ end
181
+
182
+ describe "#at_most" do
183
+ it "is relayed to the internal double and returns the recording double" do
184
+ expect(subject.should_receive(:fake_to_s).at_most(:once)).to be_a(described_class)
185
+ subject.fake_to_s
186
+ end
187
+ end
188
+
189
+ describe "#any_number_of_times" do
190
+ it "is relayed to the internal double and returns the recording double" do
191
+ expect(subject.should_receive(:fake_to_s).any_number_of_times).to be_a(described_class)
192
+ end
193
+ end
194
+
195
+ describe "#and_raise" do
196
+ let(:some_error){ Exception.new }
197
+
198
+ it "is relayed to the internal double and returns the recording double" do
199
+ expect(subject.should_receive(:fake_to_s).and_raise(some_error)).to be_a(described_class)
200
+ expect { subject.fake_to_s }.to raise_error(some_error)
201
+ end
202
+ end
203
+
204
+ describe "#and_raise" do
205
+ it "is relayed to the internal double and returns the recording double" do
206
+ expect(subject.should_receive(:fake_to_s).and_throw(:some_error)).to be_a(described_class)
207
+ expect { subject.fake_to_s }.to throw_symbol(:some_error)
135
208
  end
136
209
  end
137
210
  end