rspec-mocks 2.11.3 → 2.12.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 +16 -0
- data/README.md +26 -1
- data/features/argument_matchers/explicit.feature +2 -2
- data/features/argument_matchers/general_matchers.feature +4 -4
- data/features/argument_matchers/type_matchers.feature +1 -1
- data/features/message_expectations/README.md +4 -0
- data/features/message_expectations/any_instance.feature +1 -1
- data/features/message_expectations/call_original.feature +24 -0
- data/features/message_expectations/expect_message.feature +5 -5
- data/features/message_expectations/receive_counts.feature +7 -7
- data/features/message_expectations/warn_when_expectation_is_set_on_nil.feature +3 -3
- data/features/method_stubs/any_instance.feature +6 -7
- data/features/method_stubs/as_null_object.feature +1 -1
- data/features/method_stubs/simple_return_value.feature +2 -2
- data/features/method_stubs/stub_chain.feature +1 -1
- data/features/method_stubs/stub_implementation.feature +1 -1
- data/features/method_stubs/to_ary.feature +1 -1
- data/features/{stubbing_constants → mutating_constants}/README.md +21 -1
- data/features/mutating_constants/hiding_defined_constant.feature +64 -0
- data/features/{stubbing_constants → mutating_constants}/stub_defined_constant.feature +0 -0
- data/features/{stubbing_constants → mutating_constants}/stub_undefined_constant.feature +0 -0
- data/features/outside_rspec/configuration.feature +3 -3
- data/features/outside_rspec/standalone.feature +6 -5
- data/lib/rspec/mocks.rb +17 -1
- data/lib/rspec/mocks/any_instance.rb +12 -12
- data/lib/rspec/mocks/configuration.rb +28 -0
- data/lib/rspec/mocks/error_generator.rb +6 -0
- data/lib/rspec/mocks/example_methods.rb +34 -9
- data/lib/rspec/mocks/framework.rb +3 -2
- data/lib/rspec/mocks/instance_method_stasher.rb +70 -0
- data/lib/rspec/mocks/message_expectation.rb +49 -29
- data/lib/rspec/mocks/method_double.rb +84 -7
- data/lib/rspec/mocks/{stub_const.rb → mutate_const.rb} +117 -40
- data/lib/rspec/mocks/proxy.rb +16 -5
- data/lib/rspec/mocks/version.rb +1 -1
- data/spec/rspec/mocks/and_call_original_spec.rb +162 -0
- data/spec/rspec/mocks/any_instance_spec.rb +18 -7
- data/spec/rspec/mocks/configuration_spec.rb +26 -0
- data/spec/rspec/mocks/failing_argument_matchers_spec.rb +9 -10
- data/spec/rspec/mocks/instance_method_stasher_spec.rb +58 -0
- data/spec/rspec/mocks/mock_spec.rb +35 -35
- data/spec/rspec/mocks/{stub_const_spec.rb → mutate_const_spec.rb} +142 -13
- data/spec/rspec/mocks/null_object_mock_spec.rb +3 -2
- data/spec/rspec/mocks/partial_mock_spec.rb +102 -77
- data/spec/rspec/mocks/serialization_spec.rb +1 -2
- data/spec/rspec/mocks/stub_implementation_spec.rb +6 -6
- data/spec/rspec/mocks_spec.rb +7 -0
- data/spec/spec_helper.rb +11 -0
- metadata +79 -80
- data/lib/rspec/mocks/stashed_instance_method.rb +0 -60
- data/spec/rspec/mocks/stashed_instance_method_spec.rb +0 -53
@@ -0,0 +1,64 @@
|
|
1
|
+
Feature: Hide Defined Constant
|
2
|
+
|
3
|
+
Use `hide_const` to remove a constant for the duration of a test.
|
4
|
+
|
5
|
+
Scenario: Hide top-level constant
|
6
|
+
Given a file named "hide_const_spec.rb" with:
|
7
|
+
"""ruby
|
8
|
+
FOO = 7
|
9
|
+
|
10
|
+
describe "hiding FOO" do
|
11
|
+
it "can hide FOO" do
|
12
|
+
hide_const("FOO")
|
13
|
+
expect { FOO }.to raise_error(NameError)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "restores the hidden constant when the example completes" do
|
17
|
+
FOO.should eq(7)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
"""
|
21
|
+
When I run `rspec hide_const_spec.rb`
|
22
|
+
Then the examples should all pass
|
23
|
+
|
24
|
+
Scenario: Hide nested constant
|
25
|
+
Given a file named "hide_const_spec.rb" with:
|
26
|
+
"""ruby
|
27
|
+
module MyGem
|
28
|
+
class SomeClass
|
29
|
+
FOO = 7
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module MyGem
|
34
|
+
describe SomeClass do
|
35
|
+
it "hides the nested constant when it is fully qualified" do
|
36
|
+
hide_const("MyGem::SomeClass::FOO")
|
37
|
+
expect { SomeClass::FOO }.to raise_error(NameError)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "restores the hidden constant when the example completes" do
|
41
|
+
MyGem::SomeClass::FOO.should eq(7)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
"""
|
46
|
+
When I run `rspec hide_const_spec.rb`
|
47
|
+
Then the examples should all pass
|
48
|
+
|
49
|
+
Scenario: Hiding undefined constant
|
50
|
+
Given a file named "hide_const_spec.rb" with:
|
51
|
+
"""
|
52
|
+
describe "hiding UNDEFINED_CONSTANT" do
|
53
|
+
it "has no effect" do
|
54
|
+
hide_const("UNDEFINED_CONSTANT")
|
55
|
+
expect { UNDEFINED_CONSTANT }.to raise_error(NameError)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "is still undefined after the example completes" do
|
59
|
+
expect { UNDEFINED_CONSTANT }.to raise_error(NameError)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
"""
|
63
|
+
When I run `rspec hide_const_spec.rb`
|
64
|
+
Then the examples should all pass
|
File without changes
|
File without changes
|
@@ -25,7 +25,7 @@ Feature: configure any test framework to use rspec-mocks
|
|
25
25
|
|
26
26
|
Scenario: RSpec::Mocks::setup(object) adds double, mock, and stub methods to the submitted object
|
27
27
|
Given a file named "foo.rb" with:
|
28
|
-
"""
|
28
|
+
"""ruby
|
29
29
|
require 'rspec/mocks'
|
30
30
|
|
31
31
|
class CodeExample
|
@@ -48,7 +48,7 @@ Feature: configure any test framework to use rspec-mocks
|
|
48
48
|
|
49
49
|
Scenario: RSpec::Mocks::setup(anything) adds methods to Object
|
50
50
|
Given a file named "foo.rb" with:
|
51
|
-
"""
|
51
|
+
"""ruby
|
52
52
|
require 'rspec/mocks'
|
53
53
|
|
54
54
|
RSpec::Mocks::setup(Object.new)
|
@@ -66,7 +66,7 @@ Feature: configure any test framework to use rspec-mocks
|
|
66
66
|
|
67
67
|
Scenario: require "rspec/mocks" does not add methods to Object
|
68
68
|
Given a file named "foo.rb" with:
|
69
|
-
"""
|
69
|
+
"""ruby
|
70
70
|
require 'rspec/mocks'
|
71
71
|
|
72
72
|
obj = Object.new
|
@@ -6,7 +6,7 @@ Feature: standalone
|
|
6
6
|
|
7
7
|
Scenario: method stub outside rspec
|
8
8
|
Given a file named "example.rb" with:
|
9
|
-
"""
|
9
|
+
"""ruby
|
10
10
|
require "rspec/mocks/standalone"
|
11
11
|
|
12
12
|
greeter = double("greeter")
|
@@ -18,7 +18,7 @@ Feature: standalone
|
|
18
18
|
|
19
19
|
Scenario: message expectation outside rspec
|
20
20
|
Given a file named "example.rb" with:
|
21
|
-
"""
|
21
|
+
"""ruby
|
22
22
|
require "rspec/mocks/standalone"
|
23
23
|
|
24
24
|
greeter = double("greeter")
|
@@ -27,6 +27,7 @@ Feature: standalone
|
|
27
27
|
RSpec::Mocks.verify
|
28
28
|
"""
|
29
29
|
When I run `ruby example.rb`
|
30
|
-
Then the output should contain "
|
31
|
-
|
32
|
-
|
30
|
+
Then the output should contain "RSpec::Mocks::MockExpectationError"
|
31
|
+
And the output should contain "say_hi(any args)"
|
32
|
+
And the output should contain "expected: 1 time"
|
33
|
+
And the output should contain "received: 0 times"
|
data/lib/rspec/mocks.rb
CHANGED
@@ -23,10 +23,14 @@ module RSpec
|
|
23
23
|
space.reset_all
|
24
24
|
end
|
25
25
|
|
26
|
+
def configuration
|
27
|
+
@configuration ||= Configuration.new
|
28
|
+
end
|
29
|
+
|
26
30
|
private
|
27
31
|
|
28
32
|
def add_extensions
|
29
|
-
|
33
|
+
method_host.class_eval { include RSpec::Mocks::Methods }
|
30
34
|
Class.class_eval { include RSpec::Mocks::AnyInstance }
|
31
35
|
$_rspec_mocks_extensions_added = true
|
32
36
|
end
|
@@ -34,6 +38,18 @@ module RSpec
|
|
34
38
|
def extensions_added?
|
35
39
|
defined?($_rspec_mocks_extensions_added)
|
36
40
|
end
|
41
|
+
|
42
|
+
def method_host
|
43
|
+
# On 1.8.7, Object.ancestors.last == Kernel but
|
44
|
+
# things blow up if we include `RSpec::Mocks::Methods`
|
45
|
+
# into Kernel...not sure why.
|
46
|
+
return Object unless defined?(::BasicObject)
|
47
|
+
|
48
|
+
# MacRuby has BasicObject but it's not the root class.
|
49
|
+
return Object unless Object.ancestors.last == ::BasicObject
|
50
|
+
|
51
|
+
::BasicObject
|
52
|
+
end
|
37
53
|
end
|
38
54
|
end
|
39
55
|
end
|
@@ -30,7 +30,7 @@ module RSpec
|
|
30
30
|
modify_dup_to_remove_mock_proxy_when_invoked
|
31
31
|
__recorder
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
# @private
|
35
35
|
def rspec_verify
|
36
36
|
__recorder.verify
|
@@ -40,36 +40,36 @@ module RSpec
|
|
40
40
|
restore_dup
|
41
41
|
@__recorder = nil
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
# @private
|
45
45
|
def rspec_reset
|
46
46
|
restore_dup
|
47
47
|
__mock_proxy.reset
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
# @private
|
51
51
|
def __recorder
|
52
52
|
@__recorder ||= AnyInstance::Recorder.new(self)
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
private
|
56
56
|
def modify_dup_to_remove_mock_proxy_when_invoked
|
57
|
-
if
|
58
|
-
|
59
|
-
def __rspec_dup
|
57
|
+
if method_defined?(:dup) and !method_defined?(:__rspec_original_dup)
|
58
|
+
class_eval do
|
59
|
+
def __rspec_dup(*arguments, &block)
|
60
60
|
__remove_mock_proxy
|
61
|
-
__rspec_original_dup
|
61
|
+
__rspec_original_dup(*arguments, &block)
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
alias_method :__rspec_original_dup, :dup
|
65
65
|
alias_method :dup, :__rspec_dup
|
66
66
|
end
|
67
67
|
end
|
68
68
|
end
|
69
|
-
|
69
|
+
|
70
70
|
def restore_dup
|
71
|
-
if
|
72
|
-
|
71
|
+
if method_defined?(:__rspec_original_dup)
|
72
|
+
class_eval do
|
73
73
|
alias_method :dup, :__rspec_original_dup
|
74
74
|
remove_method :__rspec_original_dup
|
75
75
|
remove_method :__rspec_dup
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Mocks
|
3
|
+
# Provides configuration options for rspec-mocks.
|
4
|
+
class Configuration
|
5
|
+
# Adds `stub` and `should_receive` to the given
|
6
|
+
# modules or classes. This is usually only necessary
|
7
|
+
# if you application uses some proxy classes that
|
8
|
+
# "strip themselves down" to a bare minimum set of
|
9
|
+
# methods and remove `stub` and `should_receive` in
|
10
|
+
# the process.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
#
|
14
|
+
# RSpec.configure do |rspec|
|
15
|
+
# rspec.mock_with :rspec do |mocks|
|
16
|
+
# mocks.add_stub_and_should_receive_to Delegator
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
def add_stub_and_should_receive_to(*modules)
|
21
|
+
modules.each do |mod|
|
22
|
+
mod.__send__(:include, RSpec::Mocks::Methods)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -66,6 +66,12 @@ module RSpec
|
|
66
66
|
__raise "#{intro} yielded |#{arg_list(*args_to_yield)}| to block with arity of #{arity}"
|
67
67
|
end
|
68
68
|
|
69
|
+
# @private
|
70
|
+
def raise_only_valid_on_a_partial_mock(method)
|
71
|
+
__raise "#{intro} is a pure mock object. `#{method}` is only " +
|
72
|
+
"available on a partial mock object."
|
73
|
+
end
|
74
|
+
|
69
75
|
private
|
70
76
|
|
71
77
|
def intro
|
@@ -3,12 +3,18 @@ module RSpec
|
|
3
3
|
module ExampleMethods
|
4
4
|
include RSpec::Mocks::ArgumentMatchers
|
5
5
|
|
6
|
-
#
|
6
|
+
# @overload double()
|
7
|
+
# @overload double(name)
|
8
|
+
# @overload double(stubs)
|
9
|
+
# @overload double(name, stubs)
|
10
|
+
# @param name [String/Symbol] (optional) used in
|
11
|
+
# clarify intent
|
12
|
+
# @param stubs (Hash) (optional) hash of method/return-value pairs
|
13
|
+
# @return (Mock)
|
7
14
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
# Use `stubs` to declare one or more method stubs in one statement.
|
15
|
+
# Constructs an instance of [RSpec::Mocks::Mock](RSpec::Mocks::Mock) configured
|
16
|
+
# with an optional name, used for reporting in failure messages, and an optional
|
17
|
+
# hash of method/return-value pairs.
|
12
18
|
#
|
13
19
|
# @example
|
14
20
|
#
|
@@ -18,16 +24,19 @@ module RSpec
|
|
18
24
|
# card = double("card", :suit => "Spades", :rank => "A")
|
19
25
|
# card.suit #=> "Spades"
|
20
26
|
# card.rank #=> "A"
|
27
|
+
#
|
28
|
+
# @see #mock
|
29
|
+
# @see #stub
|
21
30
|
def double(*args)
|
22
31
|
declare_double('Double', *args)
|
23
32
|
end
|
24
33
|
|
25
|
-
#
|
34
|
+
# Effectively an alias for [double](#double-instance_method).
|
26
35
|
def mock(*args)
|
27
36
|
declare_double('Mock', *args)
|
28
37
|
end
|
29
38
|
|
30
|
-
#
|
39
|
+
# Effectively an alias for [double](#double-instance_method).
|
31
40
|
def stub(*args)
|
32
41
|
declare_double('Stub', *args)
|
33
42
|
end
|
@@ -79,11 +88,27 @@ module RSpec
|
|
79
88
|
# CardDeck::SUITS # => our suits array
|
80
89
|
# CardDeck::NUM_CARDS # => uninitialized constant error
|
81
90
|
def stub_const(constant_name, value, options = {})
|
82
|
-
|
91
|
+
ConstantMutator.stub(constant_name, value, options)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Hides the named constant with the given value. The constant will be
|
95
|
+
# undefined for the duration of the test.
|
96
|
+
#
|
97
|
+
# Like method stubs, the constant will be restored to its original value
|
98
|
+
# when the example completes.
|
99
|
+
#
|
100
|
+
# @param constant_name [String] The fully qualified name of the constant.
|
101
|
+
# The current constant scoping at the point of call is not considered.
|
102
|
+
#
|
103
|
+
# @example
|
104
|
+
#
|
105
|
+
# hide_const("MyClass") # => MyClass is now an undefined constant
|
106
|
+
def hide_const(constant_name)
|
107
|
+
ConstantMutator.hide(constant_name)
|
83
108
|
end
|
84
109
|
|
85
110
|
private
|
86
|
-
|
111
|
+
|
87
112
|
def declare_double(declared_as, *args)
|
88
113
|
args << {} unless Hash === args.last
|
89
114
|
args.last[:__declared_as] = declared_as
|
@@ -2,8 +2,9 @@
|
|
2
2
|
# supports wrapping rspec's mocking functionality without invading every
|
3
3
|
# object in the system.
|
4
4
|
|
5
|
+
require 'rspec/mocks/configuration'
|
5
6
|
require 'rspec/mocks/extensions/instance_exec'
|
6
|
-
require 'rspec/mocks/
|
7
|
+
require 'rspec/mocks/instance_method_stasher'
|
7
8
|
require 'rspec/mocks/method_double'
|
8
9
|
require 'rspec/mocks/methods'
|
9
10
|
require 'rspec/mocks/argument_matchers'
|
@@ -18,4 +19,4 @@ require 'rspec/mocks/error_generator'
|
|
18
19
|
require 'rspec/mocks/space'
|
19
20
|
require 'rspec/mocks/serialization'
|
20
21
|
require 'rspec/mocks/any_instance'
|
21
|
-
require 'rspec/mocks/
|
22
|
+
require 'rspec/mocks/mutate_const'
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Mocks
|
3
|
+
# @private
|
4
|
+
class InstanceMethodStasher
|
5
|
+
def initialize(klass, method)
|
6
|
+
@klass = klass
|
7
|
+
@method = method
|
8
|
+
|
9
|
+
@method_is_stashed = false
|
10
|
+
end
|
11
|
+
|
12
|
+
# @private
|
13
|
+
def method_is_stashed?
|
14
|
+
@method_is_stashed
|
15
|
+
end
|
16
|
+
|
17
|
+
# @private
|
18
|
+
def stash
|
19
|
+
return if !method_defined_directly_on_klass? || @method_is_stashed
|
20
|
+
|
21
|
+
@klass.__send__(:alias_method, stashed_method_name, @method)
|
22
|
+
@method_is_stashed = true
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# @private
|
28
|
+
def method_defined_directly_on_klass?
|
29
|
+
method_defined_on_klass? && method_owned_by_klass?
|
30
|
+
end
|
31
|
+
|
32
|
+
# @private
|
33
|
+
def method_defined_on_klass?
|
34
|
+
@klass.method_defined?(@method) || @klass.private_method_defined?(@method)
|
35
|
+
end
|
36
|
+
|
37
|
+
if ::UnboundMethod.method_defined?(:owner)
|
38
|
+
# @private
|
39
|
+
def method_owned_by_klass?
|
40
|
+
@klass.instance_method(@method).owner == @klass
|
41
|
+
end
|
42
|
+
else
|
43
|
+
# @private
|
44
|
+
def method_owned_by_klass?
|
45
|
+
# On 1.8.6, which does not support Method#owner, we have no choice but
|
46
|
+
# to assume it's defined on the klass even if it may be defined on
|
47
|
+
# a superclass.
|
48
|
+
true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
public
|
53
|
+
|
54
|
+
# @private
|
55
|
+
def stashed_method_name
|
56
|
+
"obfuscated_by_rspec_mocks__#{@method}"
|
57
|
+
end
|
58
|
+
|
59
|
+
# @private
|
60
|
+
def restore
|
61
|
+
return unless @method_is_stashed
|
62
|
+
|
63
|
+
@klass.__send__(:alias_method, @method, stashed_method_name)
|
64
|
+
@klass.__send__(:remove_method, stashed_method_name)
|
65
|
+
@method_is_stashed = false
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
@@ -9,11 +9,13 @@ module RSpec
|
|
9
9
|
protected :expected_received_count=, :expected_from=, :error_generator, :error_generator=
|
10
10
|
|
11
11
|
# @private
|
12
|
-
def initialize(error_generator, expectation_ordering, expected_from,
|
12
|
+
def initialize(error_generator, expectation_ordering, expected_from, method_double,
|
13
|
+
expected_received_count=1, opts={}, &implementation)
|
13
14
|
@error_generator = error_generator
|
14
15
|
@error_generator.opts = opts
|
15
16
|
@expected_from = expected_from
|
16
|
-
@
|
17
|
+
@method_double = method_double
|
18
|
+
@message = @method_double.method_name
|
17
19
|
@actual_received_count = 0
|
18
20
|
@expected_received_count = expected_received_count
|
19
21
|
@argument_list_matcher = ArgumentListMatcher.new(ArgumentMatchers::AnyArgsMatcher.new)
|
@@ -97,8 +99,28 @@ module RSpec
|
|
97
99
|
@implementation = implementation || build_implementation(values)
|
98
100
|
end
|
99
101
|
|
102
|
+
# Tells the object to delegate to the original unmodified method
|
103
|
+
# when it receives the message.
|
104
|
+
#
|
105
|
+
# @note This is only available on partial mock objects.
|
106
|
+
#
|
107
|
+
# @example
|
108
|
+
#
|
109
|
+
# counter.should_receive(:increment).and_call_original
|
110
|
+
# original_count = counter.count
|
111
|
+
# counter.increment
|
112
|
+
# expect(counter.count).to eq(original_count + 1)
|
113
|
+
def and_call_original
|
114
|
+
if @method_double.object.is_a?(RSpec::Mocks::TestDouble)
|
115
|
+
@error_generator.raise_only_valid_on_a_partial_mock(:and_call_original)
|
116
|
+
else
|
117
|
+
self.implementation = @method_double.original_method
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
100
121
|
# @overload and_raise
|
101
122
|
# @overload and_raise(ExceptionClass)
|
123
|
+
# @overload and_raise(ExceptionClass, message)
|
102
124
|
# @overload and_raise(exception_instance)
|
103
125
|
#
|
104
126
|
# Tells the object to raise an exception when the message is received.
|
@@ -106,17 +128,23 @@ module RSpec
|
|
106
128
|
# @note
|
107
129
|
#
|
108
130
|
# When you pass an exception class, the MessageExpectation will raise
|
109
|
-
# an instance of it, creating it with `
|
110
|
-
#
|
111
|
-
# not the class
|
131
|
+
# an instance of it, creating it with `exception` and passing `message`
|
132
|
+
# if specified. If the exception class initializer requires more than
|
133
|
+
# one parameters, you must pass in an instance and not the class,
|
134
|
+
# otherwise this method will raise an ArgumentError exception.
|
112
135
|
#
|
113
136
|
# @example
|
114
137
|
#
|
115
138
|
# car.stub(:go).and_raise
|
116
139
|
# car.stub(:go).and_raise(OutOfGas)
|
140
|
+
# car.stub(:go).and_raise(OutOfGas, "At least 2 oz of gas needed to drive")
|
117
141
|
# car.stub(:go).and_raise(OutOfGas.new(2, :oz))
|
118
|
-
def and_raise(exception=RuntimeError)
|
119
|
-
|
142
|
+
def and_raise(exception = RuntimeError, message = nil)
|
143
|
+
if exception.respond_to?(:exception)
|
144
|
+
@exception_to_raise = message ? exception.exception(message) : exception.exception
|
145
|
+
else
|
146
|
+
@exception_to_raise = exception
|
147
|
+
end
|
120
148
|
end
|
121
149
|
|
122
150
|
# @overload and_throw(symbol)
|
@@ -167,7 +195,7 @@ module RSpec
|
|
167
195
|
@order_group.handle_order_constraint self
|
168
196
|
|
169
197
|
begin
|
170
|
-
|
198
|
+
raise(@exception_to_raise) unless @exception_to_raise.nil?
|
171
199
|
Kernel::throw(*@args_to_throw) unless @args_to_throw.empty?
|
172
200
|
|
173
201
|
default_return_val = call_with_yield(&block) if !@args_to_yield.empty? || @eval_context
|
@@ -184,19 +212,6 @@ module RSpec
|
|
184
212
|
end
|
185
213
|
end
|
186
214
|
|
187
|
-
# @private
|
188
|
-
def raise_exception
|
189
|
-
if !@exception_to_raise.respond_to?(:instance_method) ||
|
190
|
-
@exception_to_raise.instance_method(:initialize).arity <= 0
|
191
|
-
raise(@exception_to_raise)
|
192
|
-
else
|
193
|
-
raise ArgumentError.new(<<-MESSAGE)
|
194
|
-
'and_raise' can only accept an Exception class if an instance can be constructed with no arguments.
|
195
|
-
#{@exception_to_raise.to_s}'s initialize method requires #{@exception_to_raise.instance_method(:initialize).arity} arguments, so you have to supply an instance instead.
|
196
|
-
MESSAGE
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
215
|
# @private
|
201
216
|
def called_max_times?
|
202
217
|
@expected_received_count != :any &&
|
@@ -301,7 +316,7 @@ MESSAGE
|
|
301
316
|
#
|
302
317
|
# @example
|
303
318
|
#
|
304
|
-
# dealer.
|
319
|
+
# dealer.should_receive(:deal_card).exactly(10).times
|
305
320
|
def exactly(n, &block)
|
306
321
|
@implementation = block if block
|
307
322
|
set_expected_received_count :exactly, n
|
@@ -313,7 +328,7 @@ MESSAGE
|
|
313
328
|
#
|
314
329
|
# @example
|
315
330
|
#
|
316
|
-
# dealer.
|
331
|
+
# dealer.should_receive(:deal_card).at_least(9).times
|
317
332
|
def at_least(n, &block)
|
318
333
|
@implementation = block if block
|
319
334
|
set_expected_received_count :at_least, n
|
@@ -325,7 +340,7 @@ MESSAGE
|
|
325
340
|
#
|
326
341
|
# @example
|
327
342
|
#
|
328
|
-
# dealer.
|
343
|
+
# dealer.should_receive(:deal_card).at_most(10).times
|
329
344
|
def at_most(n, &block)
|
330
345
|
@implementation = block if block
|
331
346
|
set_expected_received_count :at_most, n
|
@@ -336,9 +351,9 @@ MESSAGE
|
|
336
351
|
#
|
337
352
|
# @example
|
338
353
|
#
|
339
|
-
# dealer.
|
340
|
-
# dealer.
|
341
|
-
# dealer.
|
354
|
+
# dealer.should_receive(:deal_card).exactly(10).times
|
355
|
+
# dealer.should_receive(:deal_card).at_least(10).times
|
356
|
+
# dealer.should_receive(:deal_card).at_most(10).times
|
342
357
|
def times(&block)
|
343
358
|
@implementation = block if block
|
344
359
|
self
|
@@ -471,12 +486,17 @@ MESSAGE
|
|
471
486
|
# @private
|
472
487
|
class NegativeMessageExpectation < MessageExpectation
|
473
488
|
# @private
|
474
|
-
def initialize(error_generator, expectation_ordering, expected_from,
|
475
|
-
super(error_generator, expectation_ordering, expected_from,
|
489
|
+
def initialize(error_generator, expectation_ordering, expected_from, method_double, &implementation)
|
490
|
+
super(error_generator, expectation_ordering, expected_from, method_double, 0, {}, &implementation)
|
476
491
|
end
|
477
492
|
|
478
493
|
def and_return(*)
|
479
494
|
# no-op
|
495
|
+
# @deprecated and_return is not supported with negative message expectations.
|
496
|
+
RSpec.warn_deprecation <<-MSG
|
497
|
+
|
498
|
+
DEPRECATION: `and_return` with `should_not_receive` is deprecated. Called from #{caller(0)[1]}
|
499
|
+
MSG
|
480
500
|
end
|
481
501
|
|
482
502
|
# @private
|