rspec-mocks 2.11.3 → 2.12.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|