surrogate 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/.rvmrc +7 -0
- data/Gemfile +4 -0
- data/Rakefile +1 -0
- data/Readme.md +54 -0
- data/lib/surrogate/api_comparer.rb +126 -0
- data/lib/surrogate/endower.rb +108 -0
- data/lib/surrogate/hatchery.rb +48 -0
- data/lib/surrogate/hatchling.rb +78 -0
- data/lib/surrogate/method_queue.rb +14 -0
- data/lib/surrogate/options.rb +28 -0
- data/lib/surrogate/rspec/api_method_matchers.rb +246 -0
- data/lib/surrogate/rspec/substitutability_matchers.rb +24 -0
- data/lib/surrogate/rspec.rb +2 -0
- data/lib/surrogate/version.rb +3 -0
- data/lib/surrogate.rb +17 -0
- data/spec/acceptance_spec.rb +131 -0
- data/spec/defining_api_methods_spec.rb +295 -0
- data/spec/rspec/have_been_asked_for_its_spec.rb +143 -0
- data/spec/rspec/have_been_initialized_with_spec.rb +29 -0
- data/spec/rspec/have_been_told_to_spec.rb +133 -0
- data/spec/rspec/messages_spec.rb +33 -0
- data/spec/rspec/substitute_for_spec.rb +73 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/unit/api_comparer_spec.rb +138 -0
- data/surrogate.gemspec +24 -0
- metadata +92 -0
@@ -0,0 +1,295 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'define' do
|
4
|
+
describe 'in the block' do
|
5
|
+
it 'is an api method for the class' do
|
6
|
+
pristine_klass = Class.new do
|
7
|
+
Surrogate.endow self do
|
8
|
+
define(:find) { 123 }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
klass1 = pristine_klass.reprise
|
13
|
+
klass1.should_not have_been_told_to :find
|
14
|
+
klass1.find(1).should == 123
|
15
|
+
klass1.should have_been_told_to(:find).with(1)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
describe 'out of the block' do
|
21
|
+
let(:mocked_class) { Surrogate.endow Class.new }
|
22
|
+
let(:instance) { mocked_class.new }
|
23
|
+
|
24
|
+
it 'is an api method for the instance' do
|
25
|
+
mocked_class.define(:book) { 'book' }
|
26
|
+
instance.book.should == 'book'
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'declaring the behaviour' do
|
30
|
+
describe 'for verbs' do
|
31
|
+
before { mocked_class.define :wink }
|
32
|
+
|
33
|
+
describe 'will_<api_method>' do
|
34
|
+
it 'overrides the default value for the api method' do
|
35
|
+
mock1 = mocked_class.new
|
36
|
+
mock2 = mocked_class.new
|
37
|
+
mock1.will_wink :quickly
|
38
|
+
mock2.will_wink :slowly
|
39
|
+
mock1.wink.should == :quickly
|
40
|
+
mock2.wink.should == :slowly
|
41
|
+
mock1.wink.should == :quickly
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'returns the object' do
|
45
|
+
instance = mocked_class.new
|
46
|
+
instance.will_wink(:quickly).should equal instance
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'will_<api_method> with multiple arguments' do
|
51
|
+
it 'returns the object' do
|
52
|
+
instance = mocked_class.new
|
53
|
+
instance.will_wink(1, 2, 3).should equal instance
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'it creates a queue of things to find then returns to normal behaviour' do
|
57
|
+
specify 'when there is no default block' do
|
58
|
+
mock = mocked_class.new
|
59
|
+
mock.will_wink :quickly, :slowly
|
60
|
+
mock.wink.should == :quickly
|
61
|
+
mock.wink.should == :slowly
|
62
|
+
expect { mock.wink }.to raise_error Surrogate::UnpreparedMethodError
|
63
|
+
end
|
64
|
+
|
65
|
+
specify 'when there is a default block' do
|
66
|
+
mocked_class = Surrogate.endow(Class.new)
|
67
|
+
mocked_class.define(:connect) { :default }
|
68
|
+
mock = mocked_class.new
|
69
|
+
mock.will_connect 1, 2
|
70
|
+
mock.connect.should == 1
|
71
|
+
mock.connect.should == 2
|
72
|
+
mock.connect.should == :default
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
describe 'for nouns' do
|
80
|
+
before { mocked_class.define :age }
|
81
|
+
|
82
|
+
describe 'will_have_<api_method>' do
|
83
|
+
it 'defines will_have_<api_method> which overrides the default block' do
|
84
|
+
mock1 = mocked_class.new
|
85
|
+
mock2 = mocked_class.new
|
86
|
+
mock1.will_have_age 12
|
87
|
+
mock2.will_have_age 34
|
88
|
+
mock1.age.should == 12
|
89
|
+
mock2.age.should == 34
|
90
|
+
mock1.age.should == 12
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'returns the object' do
|
94
|
+
instance = mocked_class.new
|
95
|
+
instance.will_have_age(123).should equal instance
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe 'wil_have_<api_method> with multiple arguments' do
|
100
|
+
it 'returns the object' do
|
101
|
+
instance = mocked_class.new
|
102
|
+
instance.will_have_age(1,2,3).should equal instance
|
103
|
+
end
|
104
|
+
|
105
|
+
context 'it creates a queue of things to find then returns to normal behaviour' do
|
106
|
+
specify 'when there is no default block' do
|
107
|
+
mock = mocked_class.new
|
108
|
+
mock.will_have_age 12, 34
|
109
|
+
mock.age.should == 12
|
110
|
+
mock.age.should == 34
|
111
|
+
expect { mock.age }.to raise_error Surrogate::UnpreparedMethodError
|
112
|
+
end
|
113
|
+
|
114
|
+
specify 'when there is a default block' do
|
115
|
+
mocked_class = Surrogate.endow(Class.new)
|
116
|
+
mocked_class.define(:name) { 'default' }
|
117
|
+
mock = mocked_class.new
|
118
|
+
mock.will_have_name 'a', 'b'
|
119
|
+
mock.name.should == 'a'
|
120
|
+
mock.name.should == 'b'
|
121
|
+
mock.name.should == 'default'
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
|
130
|
+
context 'the api method' do
|
131
|
+
it 'takes any number of arguments' do
|
132
|
+
mocked_class.define(:meth) { 1 }
|
133
|
+
mocked_class.new.meth.should == 1
|
134
|
+
mocked_class.new.meth(1).should == 1
|
135
|
+
mocked_class.new.meth(1, 2).should == 1
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'raises an UnpreparedMethodError when it has no default block' do
|
139
|
+
mocked_class.define :meth
|
140
|
+
expect { mocked_class.new.meth }.to raise_error(Surrogate::UnpreparedMethodError, /meth/)
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'considers ivars of the same name to be its default' do
|
144
|
+
mocked_class.define :meth
|
145
|
+
mocked = mocked_class.new
|
146
|
+
mocked.instance_variable_set :@meth, 123
|
147
|
+
mocked.meth.should == 123
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'reverts to the default block if invoked and having no ivar' do
|
151
|
+
mocked_class.define(:meth) { 123 }
|
152
|
+
mocked = mocked_class.new
|
153
|
+
mocked.instance_variable_get(:@meth).should be_nil
|
154
|
+
mocked.meth.should == 123
|
155
|
+
end
|
156
|
+
|
157
|
+
describe 'initialization' do
|
158
|
+
specify 'api methods can be an initialize method' do
|
159
|
+
mocked_class.define(:initialize) { @abc = 123 }
|
160
|
+
mocked_class.new.instance_variable_get(:@abc).should == 123
|
161
|
+
end
|
162
|
+
|
163
|
+
specify 'initialize exsits even if error is raised' do
|
164
|
+
mocked_class.define(:initialize) { raise "simulate runtime error" }
|
165
|
+
expect { mocked_class.new }.to raise_error(RuntimeError, /simulate/)
|
166
|
+
expect { mocked_class.new }.to raise_error(RuntimeError, /simulate/)
|
167
|
+
end
|
168
|
+
|
169
|
+
specify 'receives args' do
|
170
|
+
mocked_class.define(:initialize) { |num1, num2| @num = num1 + num2 }
|
171
|
+
mocked_class.new(25, 75).instance_variable_get(:@num).should == 100
|
172
|
+
end
|
173
|
+
|
174
|
+
specify 'even works with inheritance' do
|
175
|
+
superclass = Class.new
|
176
|
+
superclass.send(:define_method, :initialize) { @a = 1 }
|
177
|
+
subclass = Class.new superclass
|
178
|
+
mocked_subclass = Surrogate.endow Class.new subclass
|
179
|
+
mocked_subclass.define :abc
|
180
|
+
mocked_subclass.new.instance_variable_get(:@a).should == 1
|
181
|
+
end
|
182
|
+
|
183
|
+
context 'when not an api method' do
|
184
|
+
it 'respects arity (this is probably 1.9.3 only)' do
|
185
|
+
expect { mocked_class.new(1) }.to raise_error ArgumentError, 'wrong number of arguments(1 for 0)'
|
186
|
+
end
|
187
|
+
|
188
|
+
specify 'recorded regardless of when initialize is defined in relation to mock' do
|
189
|
+
klass = Class.new do
|
190
|
+
Surrogate.endow self
|
191
|
+
def initialize(a)
|
192
|
+
@a = a
|
193
|
+
end
|
194
|
+
end
|
195
|
+
klass.new(1).should have_been_initialized_with 1
|
196
|
+
klass.new(1).instance_variable_get(:@a).should == 1
|
197
|
+
|
198
|
+
klass = Class.new do
|
199
|
+
def initialize(a)
|
200
|
+
@a = a
|
201
|
+
end
|
202
|
+
Surrogate.endow self
|
203
|
+
end
|
204
|
+
klass.new(1).should have_been_initialized_with 1
|
205
|
+
klass.new(1).instance_variable_get(:@a).should == 1
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe 'it takes a block whos return value will be used as the default' do
|
211
|
+
specify 'the block is instance evaled' do
|
212
|
+
mocked_class.define(:meth) { self }
|
213
|
+
instance = mocked_class.new
|
214
|
+
instance.meth.should equal instance
|
215
|
+
end
|
216
|
+
|
217
|
+
specify 'arguments passed to the method will be passed to the block' do
|
218
|
+
mocked_class.define(:meth) { |*args| args }
|
219
|
+
instance = mocked_class.new
|
220
|
+
instance.meth(1).should == [1]
|
221
|
+
instance.meth(1, 2).should == [1, 2]
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'remembers what it was invoked with' do
|
226
|
+
mocked_class.define(:meth) { nil }
|
227
|
+
mock = mocked_class.new
|
228
|
+
mock.meth 1
|
229
|
+
mock.meth 1, 2
|
230
|
+
mock.meth [1, 2]
|
231
|
+
mock.invocations(:meth).should == [
|
232
|
+
[1],
|
233
|
+
[1, 2],
|
234
|
+
[[1, 2]],
|
235
|
+
]
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'raises an error if asked about invocations for api methods it does not know' do
|
239
|
+
mocked_class.define :meth1
|
240
|
+
mocked_class.define :meth2
|
241
|
+
mock = mocked_class.new
|
242
|
+
expect { mock.invocations(:meth1) }.to_not raise_error
|
243
|
+
expect { mock.invocations(:meth3) }.to raise_error Surrogate::UnknownMethod, /doesn't know "meth3", only knows "initialize", "meth1", "meth2"/
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
|
249
|
+
describe 'reprise' do
|
250
|
+
it 'a repetition or further performance of the klass' do
|
251
|
+
pristine_klass = Class.new do
|
252
|
+
Surrogate.endow self do
|
253
|
+
define(:find) { 123 }
|
254
|
+
define(:bind) { 'abc' }
|
255
|
+
end
|
256
|
+
define(:peat) { true }
|
257
|
+
define(:repeat) { 321 }
|
258
|
+
end
|
259
|
+
|
260
|
+
klass1 = pristine_klass.reprise
|
261
|
+
klass1.should_not have_been_told_to :find
|
262
|
+
klass1.find(1).should == 123
|
263
|
+
klass1.should have_been_told_to(:find).with(1)
|
264
|
+
klass1.bind.should == 'abc'
|
265
|
+
|
266
|
+
klass2 = pristine_klass.reprise
|
267
|
+
klass2.will_find 456
|
268
|
+
klass2.find(2).should == 456
|
269
|
+
klass1.find.should == 123
|
270
|
+
|
271
|
+
klass1.should have_been_told_to(:find).with(1)
|
272
|
+
klass2.should have_been_told_to(:find).with(2)
|
273
|
+
klass1.should_not have_been_told_to(:find).with(2)
|
274
|
+
klass2.should_not have_been_told_to(:find).with(1)
|
275
|
+
|
276
|
+
klass1.new.peat.should == true
|
277
|
+
klass1.new.repeat.should == 321
|
278
|
+
end
|
279
|
+
|
280
|
+
it 'is a subclass of the reprised class' do
|
281
|
+
superclass = Surrogate.endow Class.new
|
282
|
+
superclass.reprise.new.should be_a_kind_of superclass
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
describe '#api_method_names' do
|
287
|
+
it 'returns the names of the api methods as symbols' do
|
288
|
+
mocked_class = Class.new do
|
289
|
+
Surrogate.endow self
|
290
|
+
define :abc
|
291
|
+
end
|
292
|
+
mocked_class.api_method_names.should == [:abc]
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'RSpec matchers', 'have_been_asked_for_its' do
|
4
|
+
let(:mocked_class) { Surrogate.endow Class.new }
|
5
|
+
let(:instance) { mocked_class.new }
|
6
|
+
|
7
|
+
describe 'default use case' do
|
8
|
+
before { mocked_class.define :name, default: 'Ayaan' }
|
9
|
+
|
10
|
+
example 'passes if has been invoked at least once' do
|
11
|
+
instance.should_not have_been_asked_for_its :name
|
12
|
+
instance.name
|
13
|
+
instance.should have_been_asked_for_its :name
|
14
|
+
instance.name
|
15
|
+
instance.should have_been_asked_for_its :name
|
16
|
+
end
|
17
|
+
|
18
|
+
example 'failure message for should' do
|
19
|
+
expect { instance.should have_been_asked_for_its :name }.to \
|
20
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /was never asked for its name/)
|
21
|
+
end
|
22
|
+
|
23
|
+
example 'failure message for should not' do
|
24
|
+
instance.name
|
25
|
+
expect { instance.should_not have_been_asked_for_its :name }.to \
|
26
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been asked for its name, but was asked 1 time/)
|
27
|
+
|
28
|
+
instance.name
|
29
|
+
expect { instance.should_not have_been_asked_for_its :name }.to \
|
30
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been asked for its name, but was asked 2 times/)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
describe 'specifying which arguments it should have been invoked with' do
|
36
|
+
before { mocked_class.define :size, default: nil }
|
37
|
+
|
38
|
+
example 'default use case' do
|
39
|
+
instance.should_not have_been_asked_for_its(:size).with(1, 2, 3)
|
40
|
+
instance.size 1, 2
|
41
|
+
instance.should_not have_been_asked_for_its(:size).with(1, 2, 3)
|
42
|
+
instance.size 1, 2, 3
|
43
|
+
instance.should have_been_asked_for_its(:size).with(1, 2, 3)
|
44
|
+
end
|
45
|
+
|
46
|
+
example 'failure message for should' do
|
47
|
+
expect { instance.should have_been_asked_for_its(:size).with(1, '2') }.to \
|
48
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked for its size with `1, "2"', but was never asked/)
|
49
|
+
|
50
|
+
instance.size 3
|
51
|
+
instance.size 4, '5'
|
52
|
+
expect { instance.should have_been_asked_for_its(:size).with(1, '2') }.to \
|
53
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked for its size with `1, "2"', but got `3', `4, "5"'/)
|
54
|
+
end
|
55
|
+
|
56
|
+
example 'failure message for should not' do
|
57
|
+
instance.size 1, '2'
|
58
|
+
expect { instance.should_not have_been_asked_for_its(:size).with(1, '2') }.to \
|
59
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /should not have been asked for its size with `1, "2"'/)
|
60
|
+
end
|
61
|
+
|
62
|
+
describe 'integration with rspec argument_matchers' do
|
63
|
+
it 'works with no_args' do
|
64
|
+
instance.should_not have_been_asked_for_its(:size).with(no_args)
|
65
|
+
instance.size(1)
|
66
|
+
instance.should_not have_been_asked_for_its(:size).with(no_args)
|
67
|
+
instance.size
|
68
|
+
instance.should have_been_asked_for_its(:size).with(no_args)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
describe 'specifying number of times invoked' do
|
75
|
+
before { mocked_class.define :value, default: nil }
|
76
|
+
|
77
|
+
example 'default use case' do
|
78
|
+
instance.should have_been_asked_for_its(:value).times(0)
|
79
|
+
instance.value
|
80
|
+
instance.should have_been_asked_for_its(:value).times(1)
|
81
|
+
instance.value
|
82
|
+
instance.should have_been_asked_for_its(:value).times(2)
|
83
|
+
end
|
84
|
+
|
85
|
+
example 'failure message for should' do
|
86
|
+
expect { instance.should have_been_asked_for_its(:value).times(1) }.to \
|
87
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked for its value 1 time, but was asked 0 times/)
|
88
|
+
|
89
|
+
instance.value
|
90
|
+
expect { instance.should have_been_asked_for_its(:value).times(2) }.to \
|
91
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked for its value 2 times, but was asked 1 time/)
|
92
|
+
end
|
93
|
+
|
94
|
+
example 'failure message for should not' do
|
95
|
+
expect { instance.should_not have_been_asked_for_its(:value).times(0) }.to \
|
96
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been asked for its value 0 times, but was/)
|
97
|
+
|
98
|
+
instance.value
|
99
|
+
expect { instance.should_not have_been_asked_for_its(:value).times(1) }.to \
|
100
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been asked for its value 1 time, but was/)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe 'conjunction of with(args) and times(n)' do
|
105
|
+
before { mocked_class.define :value, default: nil }
|
106
|
+
|
107
|
+
example 'default use case' do
|
108
|
+
instance.should have_been_asked_for_its(:value).times(0).with(1, '2')
|
109
|
+
instance.should_not have_been_asked_for_its(:value).times(1).with(1, '2')
|
110
|
+
instance.value
|
111
|
+
instance.should have_been_asked_for_its(:value).times(0).with(1, '2')
|
112
|
+
instance.should_not have_been_asked_for_its(:value).times(1).with(1, '2')
|
113
|
+
instance.value 1, '2'
|
114
|
+
instance.should have_been_asked_for_its(:value).times(1).with(1, '2')
|
115
|
+
instance.value 1, '2' # correct one
|
116
|
+
instance.value 1, '3'
|
117
|
+
instance.value 2, '2'
|
118
|
+
instance.value 1, '2', 3
|
119
|
+
instance.should have_been_asked_for_its(:value).times(2).with(1, '2')
|
120
|
+
instance.should have_been_asked_for_its(:value).with(1, '2').times(2)
|
121
|
+
end
|
122
|
+
|
123
|
+
example 'failure message for should' do
|
124
|
+
expect { instance.should have_been_asked_for_its(:value).times(1).with(1, '2') }.to \
|
125
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked for its value 1 time with `1, "2"', but was never asked/)
|
126
|
+
|
127
|
+
instance.value 1, '2'
|
128
|
+
expect { instance.should have_been_asked_for_its(:value).times(0).with(1, '2') }.to \
|
129
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked for its value 0 times with `1, "2"', but was asked 1 time/)
|
130
|
+
|
131
|
+
instance.value 1, '2'
|
132
|
+
expect { instance.should have_been_asked_for_its(:value).times(1).with(1, '2') }.to \
|
133
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked for its value 1 time with `1, "2"', but was asked 2 times/)
|
134
|
+
end
|
135
|
+
|
136
|
+
example 'failure message for should not' do
|
137
|
+
instance.value 1, '2'
|
138
|
+
instance.value 1, '2'
|
139
|
+
expect { instance.should_not have_been_asked_for_its(:value).times(2).with(1, '2') }.to \
|
140
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /should not have been asked for its value 2 times with `1, "2"'/)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'RSpec matchers', 'have_been_initialized_with' do
|
4
|
+
let(:mocked_class) { Surrogate.endow Class.new }
|
5
|
+
before { mocked_class.module_eval { def initialize(*) end } } # b/c 1.9.3 will have arity issues otherwise
|
6
|
+
|
7
|
+
it 'is the same as have_been_told_to(:initialize).with(...)' do
|
8
|
+
mocked_class.new.should have_been_initialized_with no_args
|
9
|
+
mocked_class.new.should_not have_been_initialized_with(1)
|
10
|
+
mocked_class.new(1).should have_been_initialized_with 1
|
11
|
+
mocked_class.new(1, '2').should have_been_initialized_with 1, '2'
|
12
|
+
end
|
13
|
+
|
14
|
+
def failure_message_for
|
15
|
+
yield
|
16
|
+
rescue RSpec::Expectations::ExpectationNotMetError
|
17
|
+
$!.message
|
18
|
+
end
|
19
|
+
|
20
|
+
example 'failure message for should' do
|
21
|
+
failure_message_for { mocked_class.new("1").should have_been_initialized_with 2 }.should ==
|
22
|
+
failure_message_for { mocked_class.new("1").should have_been_told_to(:initialize).with(2) }
|
23
|
+
end
|
24
|
+
|
25
|
+
example 'failure message for should not' do
|
26
|
+
failure_message_for { mocked_class.new("1").should_not have_been_initialized_with('1') }.should ==
|
27
|
+
failure_message_for { mocked_class.new("1").should_not have_been_told_to(:initialize).with('1') }
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'RSpec matchers', 'have_been_told_to' do
|
4
|
+
let(:mocked_class) { Surrogate.endow Class.new }
|
5
|
+
let(:instance) { mocked_class.new }
|
6
|
+
|
7
|
+
describe 'default use case' do
|
8
|
+
before { mocked_class.define :kick, default: [] }
|
9
|
+
|
10
|
+
example 'passes if has been invoked at least once' do
|
11
|
+
instance.should_not have_been_told_to :kick
|
12
|
+
instance.kick
|
13
|
+
instance.should have_been_told_to :kick
|
14
|
+
instance.kick
|
15
|
+
instance.should have_been_told_to :kick
|
16
|
+
end
|
17
|
+
|
18
|
+
example 'failure message for should' do
|
19
|
+
expect { instance.should have_been_told_to :kick }.to \
|
20
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /was never told to kick/)
|
21
|
+
end
|
22
|
+
|
23
|
+
example 'failure message for should not' do
|
24
|
+
instance.kick
|
25
|
+
expect { instance.should_not have_been_told_to :kick }.to \
|
26
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been told to kick, but was told to kick 1 time/)
|
27
|
+
|
28
|
+
instance.kick
|
29
|
+
expect { instance.should_not have_been_told_to :kick }.to \
|
30
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been told to kick, but was told to kick 2 times/)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
describe 'specifying which arguments it should have been invoked with' do
|
36
|
+
before { mocked_class.define :smile, default: nil }
|
37
|
+
|
38
|
+
example 'default use case' do
|
39
|
+
instance.should_not have_been_told_to(:smile).with(1, 2, 3)
|
40
|
+
instance.smile 1, 2
|
41
|
+
instance.should_not have_been_told_to(:smile).with(1, 2, 3)
|
42
|
+
instance.smile 1, 2, 3
|
43
|
+
instance.should have_been_told_to(:smile).with(1, 2, 3)
|
44
|
+
end
|
45
|
+
|
46
|
+
example 'failure message for should' do
|
47
|
+
expect { instance.should have_been_told_to(:smile).with(1, '2') }.to \
|
48
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been told to smile with `1, "2"', but was never told to/)
|
49
|
+
|
50
|
+
instance.smile 3
|
51
|
+
instance.smile 4, '5'
|
52
|
+
expect { instance.should have_been_told_to(:smile).with(1, '2') }.to \
|
53
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been told to smile with `1, "2"', but got `3', `4, "5"'/)
|
54
|
+
end
|
55
|
+
|
56
|
+
example 'failure message for should not' do
|
57
|
+
instance.smile 1, '2'
|
58
|
+
expect { instance.should_not have_been_told_to(:smile).with(1, '2') }.to \
|
59
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /should not have been told to smile with `1, "2"'/)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
describe 'specifying number of times invoked' do
|
65
|
+
before { mocked_class.define :wink, default: nil }
|
66
|
+
|
67
|
+
example 'default use case' do
|
68
|
+
instance.should have_been_told_to(:wink).times(0)
|
69
|
+
instance.wink
|
70
|
+
instance.should have_been_told_to(:wink).times(1)
|
71
|
+
instance.wink
|
72
|
+
instance.should have_been_told_to(:wink).times(2)
|
73
|
+
end
|
74
|
+
|
75
|
+
example 'failure message for should' do
|
76
|
+
expect { instance.should have_been_told_to(:wink).times(1) }.to \
|
77
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been told to wink 1 time but was told to wink 0 times/)
|
78
|
+
|
79
|
+
instance.wink
|
80
|
+
expect { instance.should have_been_told_to(:wink).times(2) }.to \
|
81
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been told to wink 2 times but was told to wink 1 time/)
|
82
|
+
end
|
83
|
+
|
84
|
+
example 'failure message for should not' do
|
85
|
+
expect { instance.should_not have_been_told_to(:wink).times(0) }.to \
|
86
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been told to wink 0 times, but was/)
|
87
|
+
|
88
|
+
instance.wink
|
89
|
+
expect { instance.should_not have_been_told_to(:wink).times(1) }.to \
|
90
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been told to wink 1 time, but was/)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe 'conjunction of with(args) and times(n)' do
|
95
|
+
before { mocked_class.define :wink, default: nil }
|
96
|
+
|
97
|
+
example 'default use case' do
|
98
|
+
instance.should have_been_told_to(:wink).times(0).with(1, '2')
|
99
|
+
instance.should_not have_been_told_to(:wink).times(1).with(1, '2')
|
100
|
+
instance.wink
|
101
|
+
instance.should have_been_told_to(:wink).times(0).with(1, '2')
|
102
|
+
instance.should_not have_been_told_to(:wink).times(1).with(1, '2')
|
103
|
+
instance.wink 1, '2'
|
104
|
+
instance.should have_been_told_to(:wink).times(1).with(1, '2')
|
105
|
+
instance.wink 1, '2' # correct one
|
106
|
+
instance.wink 1, '3'
|
107
|
+
instance.wink 2, '2'
|
108
|
+
instance.wink 1, '2', 3
|
109
|
+
instance.should have_been_told_to(:wink).times(2).with(1, '2')
|
110
|
+
instance.should have_been_told_to(:wink).with(1, '2').times(2)
|
111
|
+
end
|
112
|
+
|
113
|
+
example 'failure message for should' do
|
114
|
+
expect { instance.should have_been_told_to(:wink).times(1).with(1, '2') }.to \
|
115
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been told to wink 1 time with `1, "2"', but was never told to/)
|
116
|
+
|
117
|
+
instance.wink 1, '2'
|
118
|
+
expect { instance.should have_been_told_to(:wink).times(0).with(1, '2') }.to \
|
119
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been told to wink 0 times with `1, "2"', but got it 1 time/)
|
120
|
+
|
121
|
+
instance.wink 1, '2'
|
122
|
+
expect { instance.should have_been_told_to(:wink).times(1).with(1, '2') }.to \
|
123
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been told to wink 1 time with `1, "2"', but got it 2 times/)
|
124
|
+
end
|
125
|
+
|
126
|
+
example 'failure message for should not' do
|
127
|
+
instance.wink 1, '2'
|
128
|
+
instance.wink 1, '2'
|
129
|
+
expect { instance.should_not have_been_told_to(:wink).times(2).with(1, '2') }.to \
|
130
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, /should not have been told to wink 2 times with `1, "2"'/)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
messages_for = Surrogate::RSpec::MessagesFor
|
4
|
+
|
5
|
+
describe messages_for, 'argument inspection' do
|
6
|
+
|
7
|
+
describe 'individual argument inspection inspection' do
|
8
|
+
it 'inspects non RSpec matchers as their default inspection' do
|
9
|
+
messages_for.inspect_argument("1").should == '"1"'
|
10
|
+
messages_for.inspect_argument(1).should == "1"
|
11
|
+
messages_for.inspect_argument([/a/]).should == "[/a/]"
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'inspects no_args matcher' do
|
15
|
+
messages_for.inspect_argument(no_args).should == 'no_args'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
describe 'multiple argument inspection' do
|
21
|
+
it "wraps individual arguments in `'" do
|
22
|
+
messages_for.inspect_arguments([/a/]).should == "`/a/'"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "joins arguments with commas" do
|
26
|
+
messages_for.inspect_arguments(['x', no_args]).should == "`\"x\", no_args'"
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns no_args when the array is empty' do
|
30
|
+
messages_for.inspect_arguments([]).should == "`no_args'"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|