rspec-mocks 2.12.2 → 2.13.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/Changelog.md +30 -0
- data/README.md +16 -2
- data/lib/rspec/mocks.rb +19 -0
- data/lib/rspec/mocks/any_instance/expectation_chain.rb +9 -0
- data/lib/rspec/mocks/any_instance/recorder.rb +7 -2
- data/lib/rspec/mocks/error_generator.rb +4 -4
- data/lib/rspec/mocks/message_expectation.rb +66 -72
- data/lib/rspec/mocks/method_double.rb +4 -17
- data/lib/rspec/mocks/methods.rb +1 -1
- data/lib/rspec/mocks/proxy.rb +2 -2
- data/lib/rspec/mocks/version.rb +1 -1
- data/spec/rspec/mocks/and_call_original_spec.rb +14 -4
- data/spec/rspec/mocks/and_yield_spec.rb +13 -0
- data/spec/rspec/mocks/any_instance_spec.rb +37 -0
- data/spec/rspec/mocks/mock_spec.rb +8 -8
- data/spec/rspec/mocks/multiple_return_value_spec.rb +13 -0
- data/spec/rspec/mocks/nil_expectation_warning_spec.rb +6 -0
- data/spec/rspec/mocks/stub_spec.rb +13 -0
- data/spec/rspec/mocks/stubbed_message_expectations_spec.rb +11 -0
- metadata +61 -71
data/Changelog.md
CHANGED
@@ -1,3 +1,33 @@
|
|
1
|
+
### 2.13.0 / 2013-02-23
|
2
|
+
[full changelog](http://github.com/rspec/rspec-mocks/compare/v2.12.2...v2.13.0)
|
3
|
+
|
4
|
+
Bug fixes
|
5
|
+
|
6
|
+
* Fix bug that caused weird behavior when a method that had
|
7
|
+
previously been stubbed with multiple return values (e.g.
|
8
|
+
`obj.stub(:foo).and_return(1, 2)`) was later mocked with a
|
9
|
+
single return value (e.g. `obj.should_receive(:foo).once.and_return(1)`).
|
10
|
+
(Myron Marston)
|
11
|
+
* Fix bug related to a mock expectation for a method that already had
|
12
|
+
multiple stubs with different `with` constraints. Previously, the
|
13
|
+
first stub was used, even though it may not have matched the passed
|
14
|
+
args. The fix defers this decision until the message is received so
|
15
|
+
that the proper stub response can be chosen based on the passed
|
16
|
+
arguments (Myron Marston).
|
17
|
+
* Do not call `nil?` extra times on a mocked object, in case `nil?`
|
18
|
+
itself is expected a set number of times (Myron Marston).
|
19
|
+
* Fix `missing_default_stub_error` message so array args are handled
|
20
|
+
properly (Myron Marston).
|
21
|
+
* Explicitly disallow `any_instance.unstub!` (Ryan Jones).
|
22
|
+
* Fix `any_instance` stubbing so that it works with `Delegator`
|
23
|
+
subclasses (Myron Marston).
|
24
|
+
* Fix `and_call_original` so that it works with `Delegator` subclasses
|
25
|
+
(Myron Marston).
|
26
|
+
* Fix `any_instance.should_not_receive` when `any_instance.should_receive`
|
27
|
+
is used on the same class in the same example. Previously it would
|
28
|
+
wrongly report a failure even when the message was not received
|
29
|
+
(Myron Marston).
|
30
|
+
|
1
31
|
### 2.12.2 / 2013-01-27
|
2
32
|
[full changelog](http://github.com/rspec/rspec-mocks/compare/v2.12.1...v.2.12.2)
|
3
33
|
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# RSpec Mocks [](http://travis-ci.org/rspec/rspec-mocks) [](http://travis-ci.org/rspec/rspec-mocks) [](https://codeclimate.com/github/rspec/rspec-mocks)
|
2
2
|
|
3
3
|
rspec-mocks is a test-double framework for rspec with support for method stubs,
|
4
4
|
fakes, and message expectations on generated test-doubles and real objects
|
@@ -137,6 +137,13 @@ double.should_receive(:msg).with(*args)
|
|
137
137
|
double.should_not_receive(:msg).with(*args)
|
138
138
|
```
|
139
139
|
|
140
|
+
You can set multiple expectations for the same message if you need to:
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
double.should_receive(:msg).with("A", 1, 3)
|
144
|
+
double.should_receive(:msg).with("B", 2, 4)
|
145
|
+
```
|
146
|
+
|
140
147
|
## Argument Matchers
|
141
148
|
|
142
149
|
Arguments that are passed to `with` are compared with actual arguments
|
@@ -183,6 +190,13 @@ double.should_receive(:other_msg).ordered
|
|
183
190
|
#This will fail if the messages are received out of order
|
184
191
|
```
|
185
192
|
|
193
|
+
This can include the same message with different arguments:
|
194
|
+
|
195
|
+
```ruby
|
196
|
+
double.should_receive(:msg).with("A", 1, 3).ordered
|
197
|
+
double.should_receive(:msg).with("B", 2, 4).ordered
|
198
|
+
```
|
199
|
+
|
186
200
|
## Setting Responses
|
187
201
|
|
188
202
|
Whether you are setting a message expectation or a method stub, you can
|
@@ -233,7 +247,7 @@ double.should_receive(:msg) do |arg|
|
|
233
247
|
end
|
234
248
|
```
|
235
249
|
|
236
|
-
If the method being stubbed itself takes a block, and you need to yield to it
|
250
|
+
If the method being stubbed itself takes a block, and you need to yield to it
|
237
251
|
in some special way, you can use this:
|
238
252
|
|
239
253
|
```ruby
|
data/lib/rspec/mocks.rb
CHANGED
@@ -35,6 +35,25 @@ module RSpec
|
|
35
35
|
warn(message)
|
36
36
|
end
|
37
37
|
|
38
|
+
# @api private
|
39
|
+
KERNEL_METHOD_METHOD = ::Kernel.instance_method(:method)
|
40
|
+
|
41
|
+
# @api private
|
42
|
+
# Used internally to get a method handle for a particular object
|
43
|
+
# and method name.
|
44
|
+
#
|
45
|
+
# Includes handling for a few special cases:
|
46
|
+
#
|
47
|
+
# - Objects that redefine #method (e.g. an HTTPRequest struct)
|
48
|
+
# - BasicObject subclasses that mixin a Kernel dup (e.g. SimpleDelegator)
|
49
|
+
def method_handle_for(object, method_name)
|
50
|
+
if ::Kernel === object
|
51
|
+
KERNEL_METHOD_METHOD.bind(object).call(method_name)
|
52
|
+
else
|
53
|
+
object.method(method_name)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
38
57
|
private
|
39
58
|
|
40
59
|
def add_extensions
|
@@ -41,6 +41,15 @@ module RSpec
|
|
41
41
|
super(:should_not_receive, *args, &block)
|
42
42
|
end
|
43
43
|
|
44
|
+
# `should_not_receive` causes a failure at the point in time the
|
45
|
+
# message is wrongly received, rather than during `rspec_verify`
|
46
|
+
# at the end of an example. Thus, we should always consider a
|
47
|
+
# negative expectation fulfilled for the purposes of end-of-example
|
48
|
+
# verification (which is where this is used).
|
49
|
+
def expectation_fulfilled?
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
44
53
|
private
|
45
54
|
|
46
55
|
def invocation_order
|
@@ -91,6 +91,11 @@ module RSpec
|
|
91
91
|
raise "stub! is not supported on any_instance. Use stub instead."
|
92
92
|
end
|
93
93
|
|
94
|
+
# @private
|
95
|
+
def unstub!(*)
|
96
|
+
raise "unstub! is not supported on any_instance. Use unstub instead."
|
97
|
+
end
|
98
|
+
|
94
99
|
# @private
|
95
100
|
def stop_all_observation!
|
96
101
|
@observed_methods.each {|method_name| restore_method!(method_name)}
|
@@ -175,7 +180,7 @@ module RSpec
|
|
175
180
|
backup_method!(method_name)
|
176
181
|
@klass.class_eval(<<-EOM, __FILE__, __LINE__ + 1)
|
177
182
|
def #{method_name}(*args, &blk)
|
178
|
-
klass = ::
|
183
|
+
klass = ::RSpec::Mocks.method_handle_for(self, :#{method_name}).owner
|
179
184
|
klass.__recorder.playback!(self, :#{method_name})
|
180
185
|
self.__send__(:#{method_name}, *args, &blk)
|
181
186
|
end
|
@@ -187,7 +192,7 @@ module RSpec
|
|
187
192
|
@klass.class_eval(<<-EOM, __FILE__, __LINE__ + 1)
|
188
193
|
def #{method_name}(*args, &blk)
|
189
194
|
method_name = :#{method_name}
|
190
|
-
klass = ::
|
195
|
+
klass = ::RSpec::Mocks.method_handle_for(self, :#{method_name}).owner
|
191
196
|
invoked_instance = klass.__recorder.instance_that_received(method_name)
|
192
197
|
raise RSpec::Mocks::MockExpectationError, "The message '#{method_name}' was received by \#{self.inspect} but has already been received by \#{invoked_instance}"
|
193
198
|
end
|
@@ -28,16 +28,16 @@ module RSpec
|
|
28
28
|
end
|
29
29
|
|
30
30
|
# @private
|
31
|
-
def raise_missing_default_stub_error(expectation
|
31
|
+
def raise_missing_default_stub_error(expectation, *args)
|
32
32
|
expected_args = format_args(*expectation.expected_args)
|
33
|
-
actual_args =
|
33
|
+
actual_args = format_args(*args)
|
34
34
|
__raise "#{intro} received #{expectation.message.inspect} with unexpected arguments\n expected: #{expected_args}\n got: #{actual_args}\n Please stub a default value first if message might be received with other args as well. \n"
|
35
35
|
end
|
36
36
|
|
37
37
|
# @private
|
38
|
-
def raise_similar_message_args_error(expectation, *
|
38
|
+
def raise_similar_message_args_error(expectation, *args_for_multiple_calls)
|
39
39
|
expected_args = format_args(*expectation.expected_args)
|
40
|
-
actual_args =
|
40
|
+
actual_args = args_for_multiple_calls.collect {|a| format_args(*a)}.join(", ")
|
41
41
|
__raise "#{intro} received #{expectation.message.inspect} with unexpected arguments\n expected: #{expected_args}\n got: #{actual_args}"
|
42
42
|
end
|
43
43
|
|
@@ -3,10 +3,10 @@ module RSpec
|
|
3
3
|
|
4
4
|
class MessageExpectation
|
5
5
|
# @private
|
6
|
-
attr_accessor :error_generator
|
6
|
+
attr_accessor :error_generator, :implementation
|
7
7
|
attr_reader :message
|
8
8
|
attr_writer :expected_received_count, :expected_from, :argument_list_matcher
|
9
|
-
protected :expected_received_count=, :expected_from=, :error_generator, :error_generator=
|
9
|
+
protected :expected_received_count=, :expected_from=, :error_generator, :error_generator=, :implementation=
|
10
10
|
|
11
11
|
# @private
|
12
12
|
def initialize(error_generator, expectation_ordering, expected_from, method_double,
|
@@ -19,36 +19,16 @@ module RSpec
|
|
19
19
|
@actual_received_count = 0
|
20
20
|
@expected_received_count = expected_received_count
|
21
21
|
@argument_list_matcher = ArgumentListMatcher.new(ArgumentMatchers::AnyArgsMatcher.new)
|
22
|
-
@consecutive = false
|
23
22
|
@order_group = expectation_ordering
|
24
23
|
@at_least = @at_most = @exactly = nil
|
25
24
|
@args_to_yield = []
|
26
25
|
@failed_fast = nil
|
27
|
-
@args_to_yield_were_cloned = false
|
28
26
|
@eval_context = nil
|
29
27
|
@implementation = implementation
|
28
|
+
@values_to_return = nil
|
30
29
|
end
|
31
30
|
|
32
|
-
def implementation=(implementation)
|
33
|
-
@consecutive = false
|
34
|
-
@implementation = implementation
|
35
|
-
end
|
36
|
-
protected :implementation=
|
37
|
-
|
38
31
|
# @private
|
39
|
-
def build_child(expected_from, expected_received_count, opts={}, &implementation)
|
40
|
-
child = clone
|
41
|
-
child.expected_from = expected_from
|
42
|
-
child.implementation = implementation if implementation
|
43
|
-
child.expected_received_count = expected_received_count
|
44
|
-
child.clear_actual_received_count!
|
45
|
-
new_gen = error_generator.clone
|
46
|
-
new_gen.opts = opts
|
47
|
-
child.error_generator = new_gen
|
48
|
-
child.clone_args_to_yield(*@args_to_yield)
|
49
|
-
child.argument_list_matcher = ArgumentListMatcher.new(ArgumentMatchers::AnyArgsMatcher.new)
|
50
|
-
child
|
51
|
-
end
|
52
32
|
|
53
33
|
# @private
|
54
34
|
def expected_args
|
@@ -93,8 +73,14 @@ module RSpec
|
|
93
73
|
# counter.count # => 1
|
94
74
|
def and_return(*values, &implementation)
|
95
75
|
@expected_received_count = [@expected_received_count, values.size].max unless ignoring_args? || (@expected_received_count == 0 and @at_least)
|
96
|
-
|
97
|
-
|
76
|
+
|
77
|
+
if implementation
|
78
|
+
# TODO: deprecate `and_return { value }`
|
79
|
+
@implementation = implementation
|
80
|
+
else
|
81
|
+
@values_to_return = values
|
82
|
+
@implementation = build_implementation
|
83
|
+
end
|
98
84
|
end
|
99
85
|
|
100
86
|
# Tells the object to delegate to the original unmodified method
|
@@ -112,7 +98,7 @@ module RSpec
|
|
112
98
|
if @method_double.object.is_a?(RSpec::Mocks::TestDouble)
|
113
99
|
@error_generator.raise_only_valid_on_a_partial_mock(:and_call_original)
|
114
100
|
else
|
115
|
-
|
101
|
+
@implementation = @method_double.original_method
|
116
102
|
end
|
117
103
|
end
|
118
104
|
|
@@ -142,7 +128,7 @@ module RSpec
|
|
142
128
|
exception = message ? exception.exception(message) : exception.exception
|
143
129
|
end
|
144
130
|
|
145
|
-
|
131
|
+
@implementation = Proc.new { raise exception }
|
146
132
|
end
|
147
133
|
|
148
134
|
# @overload and_throw(symbol)
|
@@ -156,7 +142,7 @@ module RSpec
|
|
156
142
|
# car.stub(:go).and_throw(:out_of_gas)
|
157
143
|
# car.stub(:go).and_throw(:out_of_gas, :level => 0.1)
|
158
144
|
def and_throw(*args)
|
159
|
-
|
145
|
+
@implementation = Proc.new { throw *args }
|
160
146
|
end
|
161
147
|
|
162
148
|
# Tells the object to yield one or more args to a block when the message
|
@@ -166,14 +152,9 @@ module RSpec
|
|
166
152
|
#
|
167
153
|
# stream.stub(:open).and_yield(StringIO.new)
|
168
154
|
def and_yield(*args, &block)
|
169
|
-
if @args_to_yield_were_cloned
|
170
|
-
@args_to_yield.clear
|
171
|
-
@args_to_yield_were_cloned = false
|
172
|
-
end
|
173
|
-
|
174
155
|
yield @eval_context = Object.new.extend(RSpec::Mocks::InstanceExec) if block
|
175
|
-
|
176
156
|
@args_to_yield << args
|
157
|
+
@implementation = build_implementation
|
177
158
|
self
|
178
159
|
end
|
179
160
|
|
@@ -183,7 +164,7 @@ module RSpec
|
|
183
164
|
end
|
184
165
|
|
185
166
|
# @private
|
186
|
-
def invoke(*args, &block)
|
167
|
+
def invoke(parent_stub, *args, &block)
|
187
168
|
if (@expected_received_count == 0 && !@at_least) || ((@exactly || @at_most) && (@actual_received_count == @expected_received_count))
|
188
169
|
@actual_received_count += 1
|
189
170
|
@failed_fast = true
|
@@ -193,14 +174,10 @@ module RSpec
|
|
193
174
|
@order_group.handle_order_constraint self
|
194
175
|
|
195
176
|
begin
|
196
|
-
|
197
|
-
|
198
|
-
if @consecutive
|
199
|
-
call_implementation_consecutive(*args, &block)
|
200
|
-
elsif @implementation
|
177
|
+
if @implementation
|
201
178
|
call_implementation(*args, &block)
|
202
|
-
|
203
|
-
|
179
|
+
elsif parent_stub
|
180
|
+
parent_stub.invoke(nil, *args, &block)
|
204
181
|
end
|
205
182
|
ensure
|
206
183
|
@actual_received_count += 1
|
@@ -425,30 +402,12 @@ module RSpec
|
|
425
402
|
|
426
403
|
protected
|
427
404
|
|
428
|
-
def call_with_yield(&block)
|
429
|
-
@error_generator.raise_missing_block_error @args_to_yield unless block
|
430
|
-
value = nil
|
431
|
-
@args_to_yield.each do |args|
|
432
|
-
if block.arity > -1 && args.length != block.arity
|
433
|
-
@error_generator.raise_wrong_arity_error args, block.arity
|
434
|
-
end
|
435
|
-
value = @eval_context ? @eval_context.instance_exec(*args, &block) : block.call(*args)
|
436
|
-
end
|
437
|
-
value
|
438
|
-
end
|
439
|
-
|
440
|
-
def call_implementation_consecutive(*args, &block)
|
441
|
-
@value ||= call_implementation(*args, &block)
|
442
|
-
@value[[@actual_received_count, @value.size-1].min]
|
443
|
-
end
|
444
|
-
|
445
405
|
def call_implementation(*args, &block)
|
446
|
-
@implementation.arity
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
@args_to_yield_were_cloned = true
|
406
|
+
if @implementation.arity.zero?
|
407
|
+
@implementation.call(&block)
|
408
|
+
else
|
409
|
+
@implementation.call(*args, &block)
|
410
|
+
end
|
452
411
|
end
|
453
412
|
|
454
413
|
def failed_fast?
|
@@ -466,15 +425,13 @@ module RSpec
|
|
466
425
|
end
|
467
426
|
end
|
468
427
|
|
469
|
-
def clear_actual_received_count!
|
470
|
-
@actual_received_count = 0
|
471
|
-
end
|
472
|
-
|
473
428
|
private
|
474
429
|
|
475
|
-
def build_implementation
|
476
|
-
|
477
|
-
|
430
|
+
def build_implementation
|
431
|
+
Implementation.new(
|
432
|
+
@values_to_return, @args_to_yield,
|
433
|
+
@eval_context, @error_generator
|
434
|
+
).method(:call)
|
478
435
|
end
|
479
436
|
end
|
480
437
|
|
@@ -499,5 +456,42 @@ MSG
|
|
499
456
|
return @message == message
|
500
457
|
end
|
501
458
|
end
|
459
|
+
|
460
|
+
# Represents a configured implementation. Takes into account
|
461
|
+
# `and_return` and `and_yield` instructions.
|
462
|
+
# @private
|
463
|
+
class Implementation
|
464
|
+
def initialize(values_to_return, args_to_yield, eval_context, error_generator)
|
465
|
+
@values_to_return = values_to_return
|
466
|
+
@args_to_yield = args_to_yield
|
467
|
+
@eval_context = eval_context
|
468
|
+
@error_generator = error_generator
|
469
|
+
end
|
470
|
+
|
471
|
+
def call(&block)
|
472
|
+
default_return_value = perform_yield(&block)
|
473
|
+
return default_return_value unless @values_to_return
|
474
|
+
|
475
|
+
if @values_to_return.size > 1
|
476
|
+
@values_to_return.shift
|
477
|
+
else
|
478
|
+
@values_to_return.first
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
482
|
+
def perform_yield(&block)
|
483
|
+
return if @args_to_yield.empty? && @eval_context.nil?
|
484
|
+
|
485
|
+
@error_generator.raise_missing_block_error @args_to_yield unless block
|
486
|
+
value = nil
|
487
|
+
@args_to_yield.each do |args|
|
488
|
+
if block.arity > -1 && args.length != block.arity
|
489
|
+
@error_generator.raise_wrong_arity_error args, block.arity
|
490
|
+
end
|
491
|
+
value = @eval_context ? @eval_context.instance_exec(*args, &block) : block.call(*args)
|
492
|
+
end
|
493
|
+
value
|
494
|
+
end
|
495
|
+
end
|
502
496
|
end
|
503
497
|
end
|
@@ -44,7 +44,7 @@ module RSpec
|
|
44
44
|
def original_method
|
45
45
|
if @method_stasher.method_is_stashed?
|
46
46
|
# Example: a singleton method defined on @object
|
47
|
-
method_handle_for(@object, @method_stasher.stashed_method_name)
|
47
|
+
::RSpec::Mocks.method_handle_for(@object, @method_stasher.stashed_method_name)
|
48
48
|
elsif meth = original_unrecorded_any_instance_method
|
49
49
|
# Example: a method that has been mocked through
|
50
50
|
# klass.any_instance.should_receive(:msg).and_call_original
|
@@ -135,15 +135,6 @@ module RSpec
|
|
135
135
|
@object.superclass.method(@method_name)
|
136
136
|
end
|
137
137
|
end
|
138
|
-
|
139
|
-
# @private
|
140
|
-
OBJECT_METHOD_METHOD = ::Object.instance_method(:method)
|
141
|
-
|
142
|
-
# @private
|
143
|
-
def method_handle_for(object, method_name)
|
144
|
-
OBJECT_METHOD_METHOD.bind(object).call(method_name)
|
145
|
-
end
|
146
|
-
|
147
138
|
# @private
|
148
139
|
def object_singleton_class
|
149
140
|
class << @object; self; end
|
@@ -214,12 +205,8 @@ module RSpec
|
|
214
205
|
# @private
|
215
206
|
def add_expectation(error_generator, expectation_ordering, expected_from, opts, &implementation)
|
216
207
|
configure_method
|
217
|
-
expectation =
|
218
|
-
|
219
|
-
else
|
220
|
-
MessageExpectation.new(error_generator, expectation_ordering,
|
221
|
-
expected_from, self, 1, opts, &implementation)
|
222
|
-
end
|
208
|
+
expectation = MessageExpectation.new(error_generator, expectation_ordering,
|
209
|
+
expected_from, self, 1, opts, &implementation)
|
223
210
|
expectations << expectation
|
224
211
|
expectation
|
225
212
|
end
|
@@ -256,7 +243,7 @@ module RSpec
|
|
256
243
|
|
257
244
|
# @private
|
258
245
|
def proxy_for_nil_class?
|
259
|
-
@object
|
246
|
+
NilClass === @object
|
260
247
|
end
|
261
248
|
|
262
249
|
# @private
|
data/lib/rspec/mocks/methods.rb
CHANGED
@@ -82,7 +82,7 @@ module RSpec
|
|
82
82
|
if chain.length > 1
|
83
83
|
if matching_stub = __mock_proxy.__send__(:find_matching_method_stub, chain[0].to_sym)
|
84
84
|
chain.shift
|
85
|
-
matching_stub.invoke.stub_chain(*chain, &blk)
|
85
|
+
matching_stub.invoke(nil).stub_chain(*chain, &blk)
|
86
86
|
else
|
87
87
|
next_in_chain = Mock.new
|
88
88
|
stub(chain.shift) { next_in_chain }
|
data/lib/rspec/mocks/proxy.rb
CHANGED
@@ -128,9 +128,9 @@ module RSpec
|
|
128
128
|
if expectation = find_almost_matching_expectation(message, *args)
|
129
129
|
expectation.advise(*args) unless expectation.expected_messages_received?
|
130
130
|
end
|
131
|
-
stub.invoke(*args, &block)
|
131
|
+
stub.invoke(nil, *args, &block)
|
132
132
|
elsif expectation
|
133
|
-
expectation.invoke(*args, &block)
|
133
|
+
expectation.invoke(stub, *args, &block)
|
134
134
|
elsif expectation = find_almost_matching_expectation(message, *args)
|
135
135
|
expectation.advise(*args) if null_object? unless expectation.expected_messages_received?
|
136
136
|
raise_unexpected_message_args_error(expectation, *args) unless (has_negative_expectation?(message) or null_object?)
|
data/lib/rspec/mocks/version.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'delegate'
|
2
3
|
|
3
4
|
describe "and_call_original" do
|
4
5
|
context "on a partial mock object" do
|
@@ -31,10 +32,19 @@ describe "and_call_original" do
|
|
31
32
|
expect(value).to eq([:submitted_arg, :additional_yielded_arg])
|
32
33
|
end
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
context "for singleton methods" do
|
36
|
+
it 'works' do
|
37
|
+
def instance.foo; :bar; end
|
38
|
+
instance.should_receive(:foo).and_call_original
|
39
|
+
expect(instance.foo).to eq(:bar)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'works for SimpleDelegator subclasses', :if => (RUBY_VERSION.to_f > 1.8) do
|
43
|
+
instance = Class.new(SimpleDelegator).new(1)
|
44
|
+
def instance.foo; :bar; end
|
45
|
+
instance.should_receive(:foo).and_call_original
|
46
|
+
expect(instance.foo).to eq(:bar)
|
47
|
+
end
|
38
48
|
end
|
39
49
|
|
40
50
|
it 'works for methods added through an extended module' do
|
@@ -5,6 +5,19 @@ describe RSpec::Mocks::Mock do
|
|
5
5
|
let(:obj) { double }
|
6
6
|
|
7
7
|
describe "#and_yield" do
|
8
|
+
context 'when the method double has been constrained by `with`' do
|
9
|
+
it 'uses the default stub if the provided args do not match' do
|
10
|
+
obj.stub(:foo) { 15 }
|
11
|
+
obj.stub(:foo).with(:yield).and_yield
|
12
|
+
|
13
|
+
# should_receive is required to trigger the bug:
|
14
|
+
# https://github.com/rspec/rspec-mocks/issues/127
|
15
|
+
obj.should_receive(:foo)
|
16
|
+
|
17
|
+
expect(obj.foo(:dont_yield)).to eq(15)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
8
21
|
context "with eval context as block argument" do
|
9
22
|
|
10
23
|
it "evaluates the supplied block as it is read" do
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'delegate'
|
2
3
|
|
3
4
|
module RSpec
|
4
5
|
module Mocks
|
@@ -245,6 +246,14 @@ module RSpec
|
|
245
246
|
end
|
246
247
|
end
|
247
248
|
|
249
|
+
context "with #unstub!" do
|
250
|
+
it "raises with a message instructing the user to use unstub instead" do
|
251
|
+
expect do
|
252
|
+
klass.any_instance.unstub!(:foo)
|
253
|
+
end.to raise_error(/Use unstub instead/)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
248
257
|
context "unstub implementation" do
|
249
258
|
it "replaces the stubbed method with the original method" do
|
250
259
|
klass.any_instance.stub(:existing_method)
|
@@ -302,6 +311,15 @@ module RSpec
|
|
302
311
|
expect { klass.new.existing_method_with_arguments(:argument_three, :argument_four) }.to_not raise_error
|
303
312
|
end
|
304
313
|
end
|
314
|
+
|
315
|
+
context 'when used in combination with should_receive' do
|
316
|
+
it 'passes if only the expected message is received' do
|
317
|
+
klass.any_instance.should_receive(:foo)
|
318
|
+
klass.any_instance.should_not_receive(:bar)
|
319
|
+
klass.new.foo
|
320
|
+
klass.rspec_verify
|
321
|
+
end
|
322
|
+
end
|
305
323
|
end
|
306
324
|
|
307
325
|
context "with #should_receive" do
|
@@ -436,6 +454,25 @@ module RSpec
|
|
436
454
|
end
|
437
455
|
end
|
438
456
|
|
457
|
+
it 'works with a BasicObject subclass that mixes in Kernel', :if => defined?(BasicObject) do
|
458
|
+
klass = Class.new(BasicObject) do
|
459
|
+
include ::Kernel
|
460
|
+
def foo; end
|
461
|
+
end
|
462
|
+
|
463
|
+
klass.any_instance.should_receive(:foo)
|
464
|
+
klass.new.foo
|
465
|
+
end
|
466
|
+
|
467
|
+
it 'works with a SimpleDelegator subclass', :if => (RUBY_VERSION.to_f > 1.8) do
|
468
|
+
klass = Class.new(SimpleDelegator) do
|
469
|
+
def foo; end
|
470
|
+
end
|
471
|
+
|
472
|
+
klass.any_instance.should_receive(:foo)
|
473
|
+
klass.new(Object.new).foo
|
474
|
+
end
|
475
|
+
|
439
476
|
context "with argument matching" do
|
440
477
|
before do
|
441
478
|
klass.any_instance.should_receive(:foo).with(:param_one, :param_two).and_return(:result_one)
|
@@ -539,14 +539,14 @@ module RSpec
|
|
539
539
|
@double.rspec_verify
|
540
540
|
end
|
541
541
|
|
542
|
-
it "
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
expect(
|
548
|
-
|
549
|
-
|
542
|
+
it "can yield multiple times when told to do so" do
|
543
|
+
@double.stub(:foo).and_yield(:stub_value)
|
544
|
+
@double.should_receive(:foo).and_yield(:first_yield).and_yield(:second_yield)
|
545
|
+
|
546
|
+
expect { |b| @double.foo(&b) }.to yield_successive_args(:first_yield, :second_yield)
|
547
|
+
expect { |b| @double.foo(&b) }.to yield_with_args(:stub_value)
|
548
|
+
|
549
|
+
@double.rspec_verify
|
550
550
|
end
|
551
551
|
|
552
552
|
it "assigns stub return values" do
|
@@ -2,6 +2,19 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module RSpec
|
4
4
|
module Mocks
|
5
|
+
describe "a double stubbed with multiple return values" do
|
6
|
+
let(:a_double) { double }
|
7
|
+
|
8
|
+
before do
|
9
|
+
a_double.stub(:foo).and_return(:val_1, nil)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'can still set a message expectation with a single return value' do
|
13
|
+
a_double.should_receive(:foo).once.and_return(:val_1)
|
14
|
+
expect(a_double.foo).to eq(:val_1)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
5
18
|
describe "a message expectation with multiple return values and no specified count" do
|
6
19
|
before(:each) do
|
7
20
|
@double = double
|
@@ -34,6 +34,12 @@ module RSpec
|
|
34
34
|
nil.should_not_receive(:bar)
|
35
35
|
nil.foo
|
36
36
|
end
|
37
|
+
|
38
|
+
it 'does not call #nil? on a double extra times' do
|
39
|
+
dbl = double
|
40
|
+
dbl.should_receive(:nil?).once.and_return(false)
|
41
|
+
dbl.nil?
|
42
|
+
end
|
37
43
|
end
|
38
44
|
|
39
45
|
describe "#allow_message_expectations_on_nil" do
|
@@ -260,6 +260,19 @@ module RSpec
|
|
260
260
|
it "supports options" do
|
261
261
|
@stub.stub(:foo, :expected_from => "bar")
|
262
262
|
end
|
263
|
+
|
264
|
+
it 'uses the correct stubbed response when responding to a mock expectation' do
|
265
|
+
@stub.stub(:bar) { 15 }
|
266
|
+
@stub.stub(:bar).with(:eighteen) { 18 }
|
267
|
+
@stub.stub(:bar).with(:thirteen) { 13 }
|
268
|
+
|
269
|
+
@stub.should_receive(:bar).exactly(4).times
|
270
|
+
|
271
|
+
expect(@stub.bar(:blah)).to eq(15)
|
272
|
+
expect(@stub.bar(:thirteen)).to eq(13)
|
273
|
+
expect(@stub.bar(:eighteen)).to eq(18)
|
274
|
+
expect(@stub.bar).to eq(15)
|
275
|
+
end
|
263
276
|
end
|
264
277
|
|
265
278
|
end
|
@@ -43,5 +43,16 @@ describe "expection set on previously stubbed method" do
|
|
43
43
|
double.foo(3)
|
44
44
|
expect { double.rspec_verify }.to raise_error(/expected: \(4\)\s+got: \(3\)/)
|
45
45
|
end
|
46
|
+
|
47
|
+
it 'distinguishes between individual values and arrays properly' do
|
48
|
+
dbl = double
|
49
|
+
dbl.stub(:foo).with('a', ['b'])
|
50
|
+
|
51
|
+
expect {
|
52
|
+
dbl.foo(['a'], 'b')
|
53
|
+
}.to raise_error { |e|
|
54
|
+
expect(e.message).to include('expected: ("a", ["b"])', 'got: (["a"], "b")')
|
55
|
+
}
|
56
|
+
end
|
46
57
|
end
|
47
58
|
end
|
metadata
CHANGED
@@ -1,80 +1,71 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-mocks
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
hash: 59
|
3
|
+
version: !ruby/object:Gem::Version
|
5
4
|
prerelease:
|
6
|
-
|
7
|
-
- 2
|
8
|
-
- 12
|
9
|
-
- 2
|
10
|
-
version: 2.12.2
|
5
|
+
version: 2.13.0
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Steven Baker
|
14
9
|
- David Chelimsky
|
15
10
|
autorequire:
|
16
11
|
bindir: bin
|
17
12
|
cert_chain: []
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
none: false
|
24
|
-
requirements:
|
13
|
+
date: 2013-02-23 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
version_requirements: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
25
18
|
- - ~>
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
hash: 79
|
28
|
-
segments:
|
29
|
-
- 10
|
30
|
-
- 0
|
31
|
-
- 0
|
19
|
+
- !ruby/object:Gem::Version
|
32
20
|
version: 10.0.0
|
21
|
+
none: false
|
33
22
|
prerelease: false
|
34
|
-
type: :development
|
35
23
|
name: rake
|
36
|
-
requirement:
|
37
|
-
|
38
|
-
|
24
|
+
requirement: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - ~>
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: 10.0.0
|
39
29
|
none: false
|
40
|
-
|
30
|
+
type: :development
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
version_requirements: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
41
34
|
- - ~>
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
hash: 1
|
44
|
-
segments:
|
45
|
-
- 1
|
46
|
-
- 1
|
47
|
-
- 9
|
35
|
+
- !ruby/object:Gem::Version
|
48
36
|
version: 1.1.9
|
37
|
+
none: false
|
49
38
|
prerelease: false
|
50
|
-
type: :development
|
51
39
|
name: cucumber
|
52
|
-
requirement:
|
53
|
-
|
54
|
-
|
40
|
+
requirement: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 1.1.9
|
55
45
|
none: false
|
56
|
-
|
46
|
+
type: :development
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
version_requirements: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
57
50
|
- - ~>
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
hash: 25
|
60
|
-
segments:
|
61
|
-
- 0
|
62
|
-
- 4
|
63
|
-
- 11
|
51
|
+
- !ruby/object:Gem::Version
|
64
52
|
version: 0.4.11
|
53
|
+
none: false
|
65
54
|
prerelease: false
|
66
|
-
type: :development
|
67
55
|
name: aruba
|
68
|
-
requirement:
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ~>
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 0.4.11
|
61
|
+
none: false
|
62
|
+
type: :development
|
69
63
|
description: RSpec's 'test double' framework, with support for stubbing and mocking
|
70
64
|
email: rspec-users@rubyforge.org
|
71
65
|
executables: []
|
72
|
-
|
73
66
|
extensions: []
|
74
|
-
|
75
67
|
extra_rdoc_files: []
|
76
|
-
|
77
|
-
files:
|
68
|
+
files:
|
78
69
|
- lib/rspec/mocks.rb
|
79
70
|
- lib/rspec/mocks/any_instance.rb
|
80
71
|
- lib/rspec/mocks/any_instance/chain.rb
|
@@ -191,39 +182,38 @@ files:
|
|
191
182
|
- spec/rspec/mocks_spec.rb
|
192
183
|
- spec/spec_helper.rb
|
193
184
|
homepage: http://github.com/rspec/rspec-mocks
|
194
|
-
licenses:
|
185
|
+
licenses:
|
195
186
|
- MIT
|
196
187
|
post_install_message:
|
197
|
-
rdoc_options:
|
188
|
+
rdoc_options:
|
198
189
|
- --charset=UTF-8
|
199
|
-
require_paths:
|
190
|
+
require_paths:
|
200
191
|
- lib
|
201
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
segments:
|
192
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
193
|
+
requirements:
|
194
|
+
- - ! '>='
|
195
|
+
- !ruby/object:Gem::Version
|
196
|
+
version: '0'
|
197
|
+
segments:
|
208
198
|
- 0
|
209
|
-
|
210
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
199
|
+
hash: 2521574480756142487
|
211
200
|
none: false
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
201
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
202
|
+
requirements:
|
203
|
+
- - ! '>='
|
204
|
+
- !ruby/object:Gem::Version
|
205
|
+
version: '0'
|
206
|
+
segments:
|
217
207
|
- 0
|
218
|
-
|
208
|
+
hash: 2521574480756142487
|
209
|
+
none: false
|
219
210
|
requirements: []
|
220
|
-
|
221
211
|
rubyforge_project: rspec
|
222
212
|
rubygems_version: 1.8.24
|
223
213
|
signing_key:
|
224
214
|
specification_version: 3
|
225
|
-
summary: rspec-mocks-2.
|
226
|
-
test_files:
|
215
|
+
summary: rspec-mocks-2.13.0
|
216
|
+
test_files:
|
227
217
|
- features/README.md
|
228
218
|
- features/Scope.md
|
229
219
|
- features/Upgrade.md
|