rspec-mocks 3.0.0.beta2 → 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Changelog.md +104 -36
  5. data/README.md +35 -4
  6. data/lib/rspec/mocks.rb +52 -13
  7. data/lib/rspec/mocks/any_instance.rb +10 -0
  8. data/lib/rspec/mocks/any_instance/chain.rb +17 -0
  9. data/lib/rspec/mocks/any_instance/expect_chain_chain.rb +1 -1
  10. data/lib/rspec/mocks/any_instance/expectation_chain.rb +9 -6
  11. data/lib/rspec/mocks/any_instance/message_chains.rb +10 -1
  12. data/lib/rspec/mocks/any_instance/proxy.rb +112 -0
  13. data/lib/rspec/mocks/any_instance/recorder.rb +49 -18
  14. data/lib/rspec/mocks/any_instance/stub_chain.rb +5 -3
  15. data/lib/rspec/mocks/any_instance/stub_chain_chain.rb +1 -1
  16. data/lib/rspec/mocks/argument_list_matcher.rb +5 -3
  17. data/lib/rspec/mocks/argument_matchers.rb +28 -12
  18. data/lib/rspec/mocks/configuration.rb +29 -0
  19. data/lib/rspec/mocks/error_generator.rb +2 -5
  20. data/lib/rspec/mocks/example_methods.rb +122 -13
  21. data/lib/rspec/mocks/instance_method_stasher.rb +26 -2
  22. data/lib/rspec/mocks/marshal_extension.rb +41 -0
  23. data/lib/rspec/mocks/matchers/expectation_customization.rb +20 -0
  24. data/lib/rspec/mocks/matchers/receive.rb +6 -20
  25. data/lib/rspec/mocks/matchers/receive_message_chain.rb +7 -5
  26. data/lib/rspec/mocks/matchers/receive_messages.rb +1 -2
  27. data/lib/rspec/mocks/message_chain.rb +9 -9
  28. data/lib/rspec/mocks/message_expectation.rb +6 -5
  29. data/lib/rspec/mocks/method_double.rb +67 -10
  30. data/lib/rspec/mocks/method_reference.rb +1 -1
  31. data/lib/rspec/mocks/mutate_const.rb +10 -14
  32. data/lib/rspec/mocks/object_reference.rb +7 -4
  33. data/lib/rspec/mocks/proxy.rb +95 -8
  34. data/lib/rspec/mocks/space.rb +58 -9
  35. data/lib/rspec/mocks/syntax.rb +128 -210
  36. data/lib/rspec/mocks/targets.rb +6 -8
  37. data/lib/rspec/mocks/test_double.rb +16 -25
  38. data/lib/rspec/mocks/verifying_double.rb +15 -12
  39. data/lib/rspec/mocks/verifying_message_expecation.rb +3 -3
  40. data/lib/rspec/mocks/verifying_proxy.rb +23 -17
  41. data/lib/rspec/mocks/version.rb +3 -1
  42. metadata +29 -257
  43. metadata.gz.sig +0 -0
  44. data/features/README.md +0 -75
  45. data/features/Scope.md +0 -17
  46. data/features/Upgrade.md +0 -22
  47. data/features/argument_matchers/README.md +0 -27
  48. data/features/argument_matchers/explicit.feature +0 -59
  49. data/features/argument_matchers/general_matchers.feature +0 -85
  50. data/features/argument_matchers/type_matchers.feature +0 -26
  51. data/features/message_expectations/README.md +0 -75
  52. data/features/message_expectations/allow_any_instance_of.feature +0 -26
  53. data/features/message_expectations/any_instance.feature +0 -43
  54. data/features/message_expectations/block_local_expectations.feature.pending +0 -55
  55. data/features/message_expectations/call_original.feature +0 -23
  56. data/features/message_expectations/expect_message_using_expect.feature +0 -107
  57. data/features/message_expectations/expect_message_using_should_receive.feature +0 -118
  58. data/features/message_expectations/message_chains_using_expect.feature +0 -49
  59. data/features/message_expectations/receive_counts.feature +0 -209
  60. data/features/message_expectations/warn_when_expectation_is_set_on_nil.feature +0 -50
  61. data/features/method_stubs/README.md +0 -77
  62. data/features/method_stubs/allow_any_instance_of.feature +0 -136
  63. data/features/method_stubs/as_null_object.feature +0 -40
  64. data/features/method_stubs/receive_message_chain.feature +0 -51
  65. data/features/method_stubs/simple_return_value_with_allow.feature +0 -44
  66. data/features/method_stubs/simple_return_value_with_stub.feature +0 -64
  67. data/features/method_stubs/stub_implementation.feature +0 -48
  68. data/features/method_stubs/to_ary.feature +0 -51
  69. data/features/mutating_constants/README.md +0 -82
  70. data/features/mutating_constants/hiding_defined_constant.feature +0 -64
  71. data/features/mutating_constants/stub_defined_constant.feature +0 -78
  72. data/features/mutating_constants/stub_undefined_constant.feature +0 -50
  73. data/features/outside_rspec/standalone.feature +0 -33
  74. data/features/spies/spy_partial_mock_method.feature +0 -34
  75. data/features/spies/spy_pure_mock_method.feature +0 -76
  76. data/features/spies/spy_unstubbed_method.feature +0 -18
  77. data/features/step_definitions/additional_cli_steps.rb +0 -11
  78. data/features/support/env.rb +0 -22
  79. data/features/support/rubinius.rb +0 -6
  80. data/features/test_frameworks/test_unit.feature +0 -54
  81. data/features/verifying_doubles/README.md +0 -17
  82. data/features/verifying_doubles/class_doubles.feature +0 -73
  83. data/features/verifying_doubles/dynamic_classes.feature +0 -71
  84. data/features/verifying_doubles/instance_doubles.feature +0 -103
  85. data/features/verifying_doubles/object_doubles.feature +0 -65
  86. data/features/verifying_doubles/partial_doubles.feature +0 -34
  87. data/lib/rspec/mocks/extensions/marshal.rb +0 -17
  88. data/lib/rspec/mocks/framework.rb +0 -35
  89. data/lib/rspec/mocks/method_signature_verifier.rb +0 -207
  90. data/lib/rspec/mocks/ruby_features.rb +0 -24
  91. data/spec/rspec/mocks/and_call_original_spec.rb +0 -268
  92. data/spec/rspec/mocks/and_return_spec.rb +0 -23
  93. data/spec/rspec/mocks/and_yield_spec.rb +0 -126
  94. data/spec/rspec/mocks/any_instance/message_chains_spec.rb +0 -41
  95. data/spec/rspec/mocks/any_instance_spec.rb +0 -1045
  96. data/spec/rspec/mocks/array_including_matcher_spec.rb +0 -41
  97. data/spec/rspec/mocks/at_least_spec.rb +0 -123
  98. data/spec/rspec/mocks/at_most_spec.rb +0 -90
  99. data/spec/rspec/mocks/before_all_spec.rb +0 -132
  100. data/spec/rspec/mocks/block_return_value_spec.rb +0 -70
  101. data/spec/rspec/mocks/combining_implementation_instructions_spec.rb +0 -204
  102. data/spec/rspec/mocks/configuration_spec.rb +0 -242
  103. data/spec/rspec/mocks/double_spec.rb +0 -874
  104. data/spec/rspec/mocks/example_methods_spec.rb +0 -13
  105. data/spec/rspec/mocks/extensions/marshal_spec.rb +0 -54
  106. data/spec/rspec/mocks/failing_argument_matchers_spec.rb +0 -184
  107. data/spec/rspec/mocks/hash_excluding_matcher_spec.rb +0 -67
  108. data/spec/rspec/mocks/hash_including_matcher_spec.rb +0 -94
  109. data/spec/rspec/mocks/instance_method_stasher_spec.rb +0 -74
  110. data/spec/rspec/mocks/matchers/have_received_spec.rb +0 -347
  111. data/spec/rspec/mocks/matchers/receive_message_chain_spec.rb +0 -198
  112. data/spec/rspec/mocks/matchers/receive_messages_spec.rb +0 -140
  113. data/spec/rspec/mocks/matchers/receive_spec.rb +0 -418
  114. data/spec/rspec/mocks/method_signature_verifier_spec.rb +0 -272
  115. data/spec/rspec/mocks/methods_spec.rb +0 -26
  116. data/spec/rspec/mocks/mock_expectation_error_spec.rb +0 -22
  117. data/spec/rspec/mocks/mock_ordering_spec.rb +0 -114
  118. data/spec/rspec/mocks/multiple_return_value_spec.rb +0 -132
  119. data/spec/rspec/mocks/mutate_const_spec.rb +0 -542
  120. data/spec/rspec/mocks/nil_expectation_warning_spec.rb +0 -52
  121. data/spec/rspec/mocks/null_object_mock_spec.rb +0 -133
  122. data/spec/rspec/mocks/once_counts_spec.rb +0 -52
  123. data/spec/rspec/mocks/options_hash_spec.rb +0 -35
  124. data/spec/rspec/mocks/order_group_spec.rb +0 -27
  125. data/spec/rspec/mocks/partial_double_spec.rb +0 -308
  126. data/spec/rspec/mocks/partial_double_using_mocks_directly_spec.rb +0 -95
  127. data/spec/rspec/mocks/passing_argument_matchers_spec.rb +0 -145
  128. data/spec/rspec/mocks/precise_counts_spec.rb +0 -68
  129. data/spec/rspec/mocks/record_messages_spec.rb +0 -26
  130. data/spec/rspec/mocks/serialization_spec.rb +0 -90
  131. data/spec/rspec/mocks/space_spec.rb +0 -244
  132. data/spec/rspec/mocks/stash_spec.rb +0 -46
  133. data/spec/rspec/mocks/stub_chain_spec.rb +0 -168
  134. data/spec/rspec/mocks/stub_implementation_spec.rb +0 -81
  135. data/spec/rspec/mocks/stub_spec.rb +0 -327
  136. data/spec/rspec/mocks/stubbed_message_expectations_spec.rb +0 -58
  137. data/spec/rspec/mocks/syntax_agnostic_message_matchers_spec.rb +0 -101
  138. data/spec/rspec/mocks/syntax_spec.rb +0 -19
  139. data/spec/rspec/mocks/test_double_spec.rb +0 -49
  140. data/spec/rspec/mocks/to_ary_spec.rb +0 -54
  141. data/spec/rspec/mocks/twice_counts_spec.rb +0 -66
  142. data/spec/rspec/mocks/verifying_double_spec.rb +0 -590
  143. data/spec/rspec/mocks/verifying_message_expecation_spec.rb +0 -69
  144. data/spec/rspec/mocks_spec.rb +0 -192
  145. data/spec/spec_helper.rb +0 -121
@@ -1,58 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "expection set on previously stubbed method" do
4
- it "fails if message is not received after expectation is set" do
5
- double = double(:msg => nil)
6
- double.msg
7
- double.should_receive(:msg)
8
- expect { verify double }.to raise_error(RSpec::Mocks::MockExpectationError)
9
- end
10
-
11
- it "outputs arguments of similar calls" do
12
- double = double('double', :foo => true)
13
- double.should_receive(:foo).with('first')
14
- double.foo('second')
15
- double.foo('third')
16
- expect {
17
- verify double
18
- }.to raise_error(%Q|Double "double" received :foo with unexpected arguments\n expected: ("first")\n got: ("second"), ("third")|)
19
- reset double
20
- end
21
-
22
- context "with argument constraint on stub" do
23
- it "matches any args if no arg constraint set on expectation" do
24
- double = double("mock")
25
- double.stub(:foo).with(3).and_return("stub")
26
- double.should_receive(:foo).at_least(:once).and_return("expectation")
27
- double.foo
28
- verify double
29
- end
30
-
31
- it "matches specific args set on expectation" do
32
- double = double("mock")
33
- double.stub(:foo).with(3).and_return("stub")
34
- double.should_receive(:foo).at_least(:once).with(4).and_return("expectation")
35
- double.foo(4)
36
- verify double
37
- end
38
-
39
- it "fails if expectation's arg constraint is not met" do
40
- double = double("mock")
41
- double.stub(:foo).with(3).and_return("stub")
42
- double.should_receive(:foo).at_least(:once).with(4).and_return("expectation")
43
- double.foo(3)
44
- expect { verify double }.to raise_error(/expected: \(4\)\s+got: \(3\)/)
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
57
- end
58
- end
@@ -1,101 +0,0 @@
1
- require "spec_helper"
2
-
3
- module RSpec
4
- module Mocks
5
-
6
- describe ".allow_message" do
7
- let(:subject) { Object.new }
8
-
9
- it "sets up basic message allowance" do
10
- expect {
11
- ::RSpec::Mocks.allow_message(subject, :basic)
12
- }.to change {
13
- subject.respond_to?(:basic)
14
- }.to(true)
15
-
16
- expect(subject.basic).to eq(nil)
17
- end
18
-
19
- it "sets up message allowance with params and return value" do
20
- expect {
21
- ::RSpec::Mocks.allow_message(subject, :x).with(:in).and_return(:out)
22
- }.to change {
23
- subject.respond_to?(:x)
24
- }.to(true)
25
-
26
- expect(subject.x(:in)).to eq(:out)
27
- end
28
-
29
- it "supports block implementations" do
30
- ::RSpec::Mocks.allow_message(subject, :message) { :value }
31
- expect(subject.message).to eq(:value)
32
- end
33
-
34
- it "does not set an expectation that the message will be received" do
35
- ::RSpec::Mocks.allow_message(subject, :message)
36
- expect { verify subject }.not_to raise_error
37
- end
38
-
39
- it 'does not get confused when the string and symbol message form are both used' do
40
- ::RSpec::Mocks.allow_message(subject, :foo).with(1) { :a }
41
- ::RSpec::Mocks.allow_message(subject, "foo").with(2) { :b }
42
-
43
- expect(subject.foo(1)).to eq(:a)
44
- expect(subject.foo(2)).to eq(:b)
45
-
46
- reset subject
47
- end
48
- end
49
-
50
- describe ".expect_message" do
51
- let(:subject) { Object.new }
52
-
53
- it "sets up basic message expectation, verifies as uncalled" do
54
- expect {
55
- ::RSpec::Mocks.expect_message(subject, :basic)
56
- }.to change {
57
- subject.respond_to?(:basic)
58
- }.to(true)
59
-
60
- expect { verify subject }.to raise_error(RSpec::Mocks::MockExpectationError)
61
- end
62
-
63
- it "fails if never is specified and the message is called" do
64
- expect {
65
- ::RSpec::Mocks.expect_message(subject, :foo).never
66
- subject.foo
67
- }.to raise_error(/expected.*0 times/)
68
- end
69
-
70
- it "sets up basic message expectation, verifies as called" do
71
- ::RSpec::Mocks.expect_message(subject, :basic)
72
- subject.basic
73
- verify subject
74
- end
75
-
76
- it "sets up message expectation with params and return value" do
77
- ::RSpec::Mocks.expect_message(subject, :msg).with(:in).and_return(:out)
78
- expect(subject.msg(:in)).to eq(:out)
79
- verify subject
80
- end
81
-
82
- it "accepts a block implementation for the expected message" do
83
- ::RSpec::Mocks.expect_message(subject, :msg) { :value }
84
- expect(subject.msg).to eq(:value)
85
- verify subject
86
- end
87
-
88
- it 'does not get confused when the string and symbol message form are both used' do
89
- ::RSpec::Mocks.expect_message(subject, :foo).with(1)
90
- ::RSpec::Mocks.expect_message(subject, "foo").with(2)
91
-
92
- subject.foo(1)
93
- subject.foo(2)
94
-
95
- verify subject
96
- end
97
-
98
- end
99
-
100
- end
101
- end
@@ -1,19 +0,0 @@
1
- require "spec_helper"
2
-
3
- module RSpec::Mocks
4
- describe Syntax do
5
- context "when the should syntax is enabled on a non-default syntax host" do
6
- include_context "with the default mocks syntax"
7
-
8
- it "continues to warn about the should syntax" do
9
- my_host = Class.new
10
- expect(RSpec).to receive(:deprecate)
11
- Syntax.enable_should(my_host)
12
-
13
- o = Object.new
14
- o.should_receive(:bees)
15
- o.bees
16
- end
17
- end
18
- end
19
- end
@@ -1,49 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module RSpec
4
- module Mocks
5
- describe TestDouble do
6
- before(:all) do
7
- Module.class_exec do
8
- private
9
- def use; end
10
- end
11
- end
12
-
13
- after(:all) do
14
- Module.class_exec do
15
- undef use
16
- end
17
- end
18
-
19
- it 'can be extended onto a module to make it a pure test double that can mock private methods' do
20
- double = Module.new
21
- double.stub(:use)
22
- expect { double.use }.to raise_error(/private method `use' called/)
23
-
24
- double = Module.new { TestDouble.extend_onto(self) }
25
- double.should_receive(:use).and_return(:ok)
26
- expect(double.use).to be(:ok)
27
- end
28
-
29
- it 'sets the test double name when a name is passed' do
30
- double = Module.new { TestDouble.extend_onto(self, "MyDouble") }
31
- expect { double.foo }.to raise_error(/Double "MyDouble" received/)
32
- end
33
-
34
- [[:should, :expect], [:expect], [:should]].each do |syntax|
35
- context "with syntax #{syntax.inspect}" do
36
- include_context "with syntax", syntax
37
- it 'stubs the methods passed in the stubs hash' do
38
- double = Module.new do
39
- TestDouble.extend_onto(self, "MyDouble", :a => 5, :b => 10)
40
- end
41
-
42
- expect(double.a).to eq(5)
43
- expect(double.b).to eq(10)
44
- end
45
- end
46
- end
47
- end
48
- end
49
- end
@@ -1,54 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe "a double receiving to_ary" do
4
- shared_examples "to_ary" do
5
- it "can be overridden with a stub" do
6
- obj.stub(:to_ary) { :non_nil_value }
7
- expect(obj.to_ary).to be(:non_nil_value)
8
- end
9
-
10
- it "responds when overriden" do
11
- obj.stub(:to_ary) { :non_nil_value }
12
- expect(obj).to respond_to(:to_ary)
13
- end
14
-
15
- it "supports Array#flatten" do
16
- obj = double('foo')
17
- expect([obj].flatten).to eq([obj])
18
- end
19
- end
20
-
21
- context "double as_null_object" do
22
- let(:obj) { double('obj').as_null_object }
23
- include_examples "to_ary"
24
-
25
- it "does respond to to_ary" do
26
- expect(obj).to respond_to(:to_ary)
27
- end
28
-
29
- it "does respond to to_a" do
30
- expect(obj).to respond_to(:to_a)
31
- end
32
-
33
- it "returns nil" do
34
- expect(obj.to_ary).to eq nil
35
- end
36
- end
37
-
38
- context "double without as_null_object" do
39
- let(:obj) { double('obj') }
40
- include_examples "to_ary"
41
-
42
- it "doesn't respond to to_ary" do
43
- expect(obj).not_to respond_to(:to_ary)
44
- end
45
-
46
- it "doesn't respond to to_a", :if => ( RUBY_VERSION.to_f > 1.8 ) do
47
- expect(obj).not_to respond_to(:to_a)
48
- end
49
-
50
- it "raises " do
51
- expect { obj.to_ary }.to raise_error(NoMethodError)
52
- end
53
- end
54
- end
@@ -1,66 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module RSpec
4
- module Mocks
5
- describe "#twice" do
6
- before(:each) do
7
- @double = double("test double")
8
- end
9
-
10
- it "passes when called twice" do
11
- @double.should_receive(:do_something).twice
12
- @double.do_something
13
- @double.do_something
14
- verify @double
15
- end
16
-
17
- it "passes when called twice with specified args" do
18
- @double.should_receive(:do_something).twice.with("1", 1)
19
- @double.do_something("1", 1)
20
- @double.do_something("1", 1)
21
- verify @double
22
- end
23
-
24
- it "passes when called twice with unspecified args" do
25
- @double.should_receive(:do_something).twice
26
- @double.do_something("1")
27
- @double.do_something(1)
28
- verify @double
29
- end
30
-
31
- it "fails fast when call count is higher than expected" do
32
- @double.should_receive(:do_something).twice
33
- @double.do_something
34
- @double.do_something
35
- expect {
36
- @double.do_something
37
- }.to raise_error(RSpec::Mocks::MockExpectationError)
38
- end
39
-
40
- it "fails when call count is lower than expected" do
41
- @double.should_receive(:do_something).twice
42
- @double.do_something
43
- expect {
44
- verify @double
45
- }.to raise_error(RSpec::Mocks::MockExpectationError)
46
- end
47
-
48
- it "fails when called wrong args on the first call" do
49
- @double.should_receive(:do_something).twice.with("1", 1)
50
- expect {
51
- @double.do_something(1, "1")
52
- }.to raise_error(RSpec::Mocks::MockExpectationError)
53
- reset @double
54
- end
55
-
56
- it "fails when called with wrong args on the second call" do
57
- @double.should_receive(:do_something).twice.with("1", 1)
58
- @double.do_something("1", 1)
59
- expect {
60
- @double.do_something(1, "1")
61
- }.to raise_error(RSpec::Mocks::MockExpectationError)
62
- reset @double
63
- end
64
- end
65
- end
66
- end
@@ -1,590 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class LoadedClass
4
- extend RSpec::Mocks::RubyFeatures
5
-
6
- M = :m
7
- N = :n
8
- INSTANCE = LoadedClass.new
9
-
10
- class << self
11
-
12
- def respond_to?(method_name, include_all = false)
13
- return true if method_name == :dynamic_class_method
14
- super
15
- end
16
-
17
- def defined_class_method
18
- end
19
-
20
- def send
21
- # fake out!
22
- end
23
-
24
- protected
25
-
26
- def defined_protected_class_method
27
- end
28
-
29
- private
30
-
31
- def defined_private_class_method
32
- end
33
-
34
- end
35
-
36
- def defined_instance_method
37
- end
38
-
39
- if required_kw_args_supported?
40
- # Need to eval this since it is invalid syntax on earlier rubies.
41
- eval <<-RUBY
42
- def kw_args_method(optional_arg:'hello', required_arg:)
43
- end
44
- RUBY
45
- end
46
-
47
- def send(*)
48
- end
49
-
50
- def respond_to?(method_name, include_all = false)
51
- return true if method_name == :dynamic_instance_method
52
- super
53
- end
54
-
55
- class Nested; end
56
-
57
- protected
58
-
59
- def defined_protected_method
60
- end
61
-
62
- private
63
-
64
- def defined_private_method
65
- "wink wink ;)"
66
- end
67
-
68
- end
69
-
70
- module RSpec
71
- module Mocks
72
- describe 'verifying doubles' do
73
- describe 'instance doubles' do
74
- describe 'when doubled class is not loaded' do
75
- include_context "with isolated configuration"
76
-
77
- before do
78
- RSpec::Mocks.configuration.verify_doubled_constant_names = false
79
- end
80
-
81
- it 'allows any instance method to be stubbed' do
82
- o = instance_double('NonloadedClass')
83
- o.stub(:undefined_instance_method).with(:arg).and_return(true)
84
- expect(o.undefined_instance_method(:arg)).to eq(true)
85
- end
86
-
87
- it 'allows any instance method to be expected' do
88
- o = instance_double("NonloadedClass")
89
-
90
- expect(o).to receive(:undefined_instance_method).
91
- with(:arg).
92
- and_return(true)
93
-
94
- expect(o.undefined_instance_method(:arg)).to eq(true)
95
- end
96
-
97
- it 'handles classes that are materialized after mocking' do
98
- stub_const "A::B", Object.new
99
- o = instance_double "A", :undefined_instance_method => true
100
-
101
- expect(o.undefined_instance_method).to eq(true)
102
- end
103
-
104
- context 'for null objects' do
105
- let(:o) { instance_double('NonLoadedClass').as_null_object }
106
-
107
- it 'returns self from any message' do
108
- expect(o.a.b.c).to be(o)
109
- end
110
-
111
- it 'reports it responds to any message' do
112
- expect(o.respond_to?(:a)).to be true
113
- expect(o.respond_to?(:a, false)).to be true
114
- expect(o.respond_to?(:a, true)).to be true
115
- end
116
- end
117
- end
118
-
119
- describe 'when doubled class is loaded' do
120
- include_context "with isolated configuration"
121
-
122
- before do
123
- RSpec::Mocks.configuration.verify_doubled_constant_names = true
124
- end
125
-
126
- it 'only allows instance methods that exist to be stubbed' do
127
- o = instance_double('LoadedClass', :defined_instance_method => 1)
128
- expect(o.defined_instance_method).to eq(1)
129
-
130
- prevents { o.stub(:undefined_instance_method) }
131
- prevents { o.stub(:defined_class_method) }
132
- end
133
-
134
- it 'only allows instance methods that exist to be expected' do
135
- o = instance_double('LoadedClass')
136
- expect(o).to receive(:defined_instance_method)
137
- o.defined_instance_method
138
-
139
- prevents { expect(o).to receive(:undefined_instance_method) }
140
- prevents { expect(o).to receive(:defined_class_method) }
141
- prevents { o.should_receive(:undefined_instance_method) }
142
- prevents { o.should_receive(:defined_class_method) }
143
- end
144
-
145
- it 'allows `send` to be stubbed if it is defined on the class' do
146
- o = instance_double('LoadedClass')
147
- allow(o).to receive(:send).and_return("received")
148
- expect(o.send(:msg)).to eq("received")
149
- end
150
-
151
- it 'gives a descriptive error message for NoMethodError' do
152
- o = instance_double("LoadedClass")
153
- expect {
154
- o.defined_private_method
155
- }.to raise_error(NoMethodError,
156
- /Double "LoadedClass \(instance\)"/)
157
- end
158
-
159
- describe "method visibility" do
160
- shared_examples_for "preserves method visibility" do |visibility|
161
- method_name = :"defined_#{visibility}_method"
162
-
163
- it "can allow a #{visibility} instance method" do
164
- o = instance_double('LoadedClass')
165
- allow(o).to receive(method_name).and_return(3)
166
- expect(o.send method_name).to eq(3)
167
- end
168
-
169
- it "can expect a #{visibility} instance method" do
170
- o = instance_double('LoadedClass')
171
- expect(o).to receive(method_name)
172
- o.send method_name
173
- end
174
-
175
- it "preserves #{visibility} visibility when allowing a #{visibility} method" do
176
- preserves_visibility(method_name, visibility) do
177
- instance_double('LoadedClass').tap do |o|
178
- allow(o).to receive(method_name)
179
- end
180
- end
181
- end
182
-
183
- it "preserves #{visibility} visibility when expecting a #{visibility} method" do
184
- preserves_visibility(method_name, visibility) do
185
- instance_double('LoadedClass').tap do |o|
186
- expect(o).to receive(method_name).at_least(:once)
187
- o.send(method_name) # to satisfy the expectation
188
- end
189
- end
190
- end
191
-
192
- it "preserves #{visibility} visibility on a null object" do
193
- preserves_visibility(method_name, visibility) do
194
- instance_double('LoadedClass').as_null_object
195
- end
196
- end
197
- end
198
-
199
- include_examples "preserves method visibility", :private
200
- include_examples "preserves method visibility", :protected
201
- end
202
-
203
- it 'does not allow dynamic methods to be expected' do
204
- # This isn't possible at the moment since an instance of the class
205
- # would be required for the verification, and we only have the
206
- # class itself.
207
- #
208
- # This spec exists as "negative" documentation of the absence of a
209
- # feature, to highlight the asymmetry from class doubles (that do
210
- # support this behaviour).
211
- prevents {
212
- instance_double('LoadedClass', :dynamic_instance_method => 1)
213
- }
214
- end
215
-
216
- it 'checks the arity of stubbed methods' do
217
- o = instance_double('LoadedClass')
218
- prevents {
219
- expect(o).to receive(:defined_instance_method).with(:a)
220
- }
221
- end
222
-
223
- it 'checks that stubbed methods are invoked with the correct arity' do
224
- o = instance_double('LoadedClass', :defined_instance_method => 25)
225
- expect {
226
- o.defined_instance_method(:a)
227
- }.to raise_error(ArgumentError,
228
- "Wrong number of arguments. Expected 0, got 1.")
229
- end
230
-
231
- if required_kw_args_supported?
232
- it 'allows keyword arguments' do
233
- o = instance_double('LoadedClass', :kw_args_method => true)
234
- expect(o.kw_args_method(:required_arg => 'something')).to eq(true)
235
- end
236
-
237
- it 'checks that stubbed methods with required keyword args are ' +
238
- 'invoked with the required arguments' do
239
- o = instance_double('LoadedClass', :kw_args_method => true)
240
- expect {
241
- o.kw_args_method(:optional_arg => 'something')
242
- }.to raise_error(ArgumentError)
243
- end
244
- end
245
-
246
- it 'allows class to be specified by constant' do
247
- o = instance_double(LoadedClass, :defined_instance_method => 1)
248
- expect(o.defined_instance_method).to eq(1)
249
- end
250
-
251
- context 'for null objects' do
252
- let(:o) { instance_double('LoadedClass').as_null_object }
253
-
254
- it 'only allows defined methods' do
255
- expect(o.defined_instance_method).to eq(o)
256
- prevents { o.undefined_method }
257
- prevents { o.send(:undefined_method) }
258
- prevents { o.__send__(:undefined_method) }
259
- end
260
-
261
- it 'reports what public messages it responds to accurately' do
262
- expect(o.respond_to?(:defined_instance_method)).to be true
263
- expect(o.respond_to?(:defined_instance_method, true)).to be true
264
- expect(o.respond_to?(:defined_instance_method, false)).to be true
265
-
266
- expect(o.respond_to?(:undefined_method)).to be false
267
- expect(o.respond_to?(:undefined_method, true)).to be false
268
- expect(o.respond_to?(:undefined_method, false)).to be false
269
- end
270
-
271
- it 'reports that it responds to defined private methods when the appropriate arg is passed' do
272
- expect(o.respond_to?(:defined_private_method)).to be false
273
- expect(o.respond_to?(:defined_private_method, true)).to be true
274
- expect(o.respond_to?(:defined_private_method, false)).to be false
275
- end
276
-
277
- if RUBY_VERSION.to_f < 2.0 # respond_to?(:protected_method) changed behavior in Ruby 2.0.
278
- it 'reports that it responds to protected methods' do
279
- expect(o.respond_to?(:defined_protected_method)).to be true
280
- expect(o.respond_to?(:defined_protected_method, true)).to be true
281
- expect(o.respond_to?(:defined_protected_method, false)).to be true
282
- end
283
- else
284
- it 'reports that it responds to protected methods when the appropriate arg is passed' do
285
- expect(o.respond_to?(:defined_protected_method)).to be false
286
- expect(o.respond_to?(:defined_protected_method, true)).to be true
287
- expect(o.respond_to?(:defined_protected_method, false)).to be false
288
- end
289
- end
290
- end
291
- end
292
-
293
- it 'cannot be constructed with a non-module object' do
294
- expect {
295
- instance_double(Object.new)
296
- }.to raise_error(/Module or String expected/)
297
- end
298
-
299
- it 'can be constructed with a struct' do
300
- o = instance_double(Struct.new(:defined_method), :defined_method => 1)
301
-
302
- expect(o.defined_method).to eq(1)
303
- end
304
- end
305
-
306
- describe 'class doubles' do
307
- describe 'when doubled class is not loaded' do
308
- include_context "with isolated configuration"
309
-
310
- before do
311
- RSpec::Mocks.configuration.verify_doubled_constant_names = false
312
- end
313
-
314
- it 'allows any method to be stubbed' do
315
- o = class_double('NonloadedClass')
316
- allow(o).to receive(:undefined_instance_method).with(:arg).and_return(1)
317
- expect(o.undefined_instance_method(:arg)).to eq(1)
318
- end
319
- end
320
-
321
- describe 'when doubled class is loaded' do
322
- include_context "with isolated configuration"
323
-
324
- before do
325
- RSpec::Mocks.configuration.verify_doubled_constant_names = true
326
- end
327
-
328
- it 'only allows class methods that exist to be stubbed' do
329
- o = class_double('LoadedClass', :defined_class_method => 1)
330
- expect(o.defined_class_method).to eq(1)
331
-
332
- prevents { o.stub(:undefined_instance_method) }
333
- prevents { o.stub(:defined_instance_method) }
334
- end
335
-
336
- it 'only allows class methods that exist to be expected' do
337
- o = class_double('LoadedClass')
338
- expect(o).to receive(:defined_class_method)
339
- o.defined_class_method
340
-
341
- prevents { expect(o).to receive(:undefined_instance_method) }
342
- prevents { expect(o).to receive(:defined_instance_method) }
343
- prevents { o.should_receive(:undefined_instance_method) }
344
- prevents { o.should_receive(:defined_instance_method) }
345
- end
346
-
347
- it 'gives a descriptive error message for NoMethodError' do
348
- o = class_double("LoadedClass")
349
- expect {
350
- o.defined_private_class_method
351
- }.to raise_error(NoMethodError, /Double "LoadedClass"/)
352
- end
353
-
354
- describe "method visibility" do
355
- shared_examples_for "preserves method visibility" do |visibility|
356
- method_name = :"defined_#{visibility}_class_method"
357
-
358
- it "can allow a #{visibility} instance method" do
359
- o = class_double('LoadedClass')
360
- allow(o).to receive(method_name).and_return(3)
361
- expect(o.send method_name).to eq(3)
362
- end
363
-
364
- it "can expect a #{visibility} instance method" do
365
- o = class_double('LoadedClass')
366
- expect(o).to receive(method_name)
367
- o.send method_name
368
- end
369
-
370
- it "preserves #{visibility} visibility when allowing a #{visibility} method" do
371
- preserves_visibility(method_name, visibility) do
372
- class_double('LoadedClass').tap do |o|
373
- allow(o).to receive(method_name)
374
- end
375
- end
376
- end
377
-
378
- it "preserves #{visibility} visibility when expecting a #{visibility} method" do
379
- preserves_visibility(method_name, visibility) do
380
- class_double('LoadedClass').tap do |o|
381
- expect(o).to receive(method_name).at_least(:once)
382
- o.send(method_name) # to satisfy the expectation
383
- end
384
- end
385
- end
386
-
387
- it "preserves #{visibility} visibility on a null object" do
388
- preserves_visibility(method_name, visibility) do
389
- class_double('LoadedClass').as_null_object
390
- end
391
- end
392
- end
393
-
394
- include_examples "preserves method visibility", :private
395
- include_examples "preserves method visibility", :protected
396
- end
397
-
398
- it 'checks that stubbed methods are invoked with the correct arity' do
399
- o = class_double('LoadedClass', :defined_class_method => 1)
400
- expect {
401
- o.defined_class_method(:a)
402
- }.to raise_error(ArgumentError)
403
- end
404
-
405
- it 'allows dynamically defined class method stubs with arguments' do
406
- o = class_double('LoadedClass')
407
- allow(o).to receive(:dynamic_class_method).with(:a) { 1 }
408
-
409
- expect(o.dynamic_class_method(:a)).to eq(1)
410
- end
411
-
412
- it 'allows dynamically defined class method mocks with arguments' do
413
- o = class_double('LoadedClass')
414
- expect(o).to receive(:dynamic_class_method).with(:a)
415
-
416
- o.dynamic_class_method(:a)
417
- end
418
-
419
- it 'allows dynamically defined class methods to be expected' do
420
- o = class_double('LoadedClass', :dynamic_class_method => 1)
421
- expect(o.dynamic_class_method).to eq(1)
422
- end
423
-
424
- it 'allows class to be specified by constant' do
425
- o = class_double(LoadedClass, :defined_class_method => 1)
426
- expect(o.defined_class_method).to eq(1)
427
- end
428
-
429
- it 'can replace existing constants for the duration of the test' do
430
- original = LoadedClass
431
- object = class_double('LoadedClass').as_stubbed_const
432
- expect(object).to receive(:defined_class_method)
433
-
434
- expect(LoadedClass).to eq(object)
435
- ::RSpec::Mocks.teardown
436
- ::RSpec::Mocks.setup
437
- expect(LoadedClass).to eq(original)
438
- end
439
-
440
- it 'can transfer nested constants to the double' do
441
- class_double("LoadedClass").
442
- as_stubbed_const(:transfer_nested_constants => true)
443
- expect(LoadedClass::M).to eq(:m)
444
- expect(LoadedClass::N).to eq(:n)
445
- end
446
-
447
- it 'correctly verifies expectations when constant is removed' do
448
- dbl1 = class_double(LoadedClass::Nested).as_stubbed_const
449
- class_double(LoadedClass).as_stubbed_const
450
-
451
- prevents {
452
- expect(dbl1).to receive(:undefined_class_method)
453
- }
454
- end
455
-
456
- it 'only allows defined methods for null objects' do
457
- o = class_double('LoadedClass').as_null_object
458
-
459
- expect(o.defined_class_method).to eq(o)
460
- prevents { o.undefined_method }
461
- end
462
- end
463
-
464
- it 'cannot be constructed with a non-module object' do
465
- expect {
466
- class_double(Object.new)
467
- }.to raise_error(/Module or String expected/)
468
- end
469
-
470
- it "trying to raise a class_double raises a TypeError", :unless => RUBY_VERSION == '1.9.2' do
471
- subject = Object.new
472
- class_double("StubbedError").as_stubbed_const
473
- allow(subject).to receive(:some_method).and_raise(StubbedError)
474
- expect { subject.some_method }.to raise_error(TypeError, 'exception class/object expected')
475
- end
476
-
477
- end
478
-
479
- describe 'object doubles' do
480
- it 'replaces an unloaded constant' do
481
- o = object_double("LoadedClass::NOINSTANCE").as_stubbed_const
482
-
483
- expect(LoadedClass::NOINSTANCE).to eq(o)
484
-
485
- expect(o).to receive(:undefined_instance_method)
486
- o.undefined_instance_method
487
- end
488
-
489
- it 'replaces a constant by name and verifies instances methods' do
490
- o = object_double("LoadedClass::INSTANCE").as_stubbed_const
491
-
492
- expect(LoadedClass::INSTANCE).to eq(o)
493
-
494
- prevents { expect(o).to receive(:undefined_instance_method) }
495
- prevents { expect(o).to receive(:defined_class_method) }
496
- prevents { o.defined_instance_method }
497
-
498
- expect(o).to receive(:defined_instance_method)
499
- o.defined_instance_method
500
- expect(o).to receive(:defined_private_method)
501
- o.send :defined_private_method
502
- end
503
-
504
- it 'can create a double that matches the interface of any arbitrary object' do
505
- o = object_double(LoadedClass.new)
506
-
507
- prevents { expect(o).to receive(:undefined_instance_method) }
508
- prevents { expect(o).to receive(:defined_class_method) }
509
- prevents { o.defined_instance_method }
510
-
511
- expect(o).to receive(:defined_instance_method)
512
- o.defined_instance_method
513
- expect(o).to receive(:defined_private_method)
514
- o.send :defined_private_method
515
- end
516
-
517
- it 'does not allow transferring constants to an object' do
518
- expect {
519
- object_double("LoadedClass::INSTANCE").
520
- as_stubbed_const(:transfer_nested_constants => true)
521
- }.to raise_error(/Cannot transfer nested constants/)
522
- end
523
-
524
- it 'does not allow as_stubbed_constant for real objects' do
525
- expect {
526
- object_double(LoadedClass.new).as_stubbed_const
527
- }.to raise_error(/Can not perform constant replacement with an object/)
528
- end
529
-
530
- it 'is not a module' do
531
- expect(object_double("LoadedClass::INSTANCE")).to_not be_a(Module)
532
- end
533
- end
534
-
535
-
536
- describe 'when verify_doubled_constant_names config option is set' do
537
- include_context "with isolated configuration"
538
-
539
- before do
540
- RSpec::Mocks.configuration.verify_doubled_constant_names = true
541
- end
542
-
543
- it 'prevents creation of instance doubles for unloaded constants' do
544
- expect {
545
- instance_double('LoadedClas')
546
- }.to raise_error(VerifyingDoubleNotDefinedError)
547
- end
548
-
549
- it 'prevents creation of class doubles for unloaded constants' do
550
- expect {
551
- class_double('LoadedClas')
552
- }.to raise_error(VerifyingDoubleNotDefinedError)
553
- end
554
- end
555
-
556
- it 'can only be named with a string or a module' do
557
- expect { instance_double(1) }.to raise_error(ArgumentError)
558
- expect { instance_double(nil) }.to raise_error(ArgumentError)
559
- end
560
-
561
- def preserves_visibility(method_name, visibility)
562
- double = yield
563
-
564
- expect {
565
- # send bypasses visbility, so we use eval instead.
566
- eval("double.#{method_name}")
567
- }.to raise_error(NoMethodError, a_message_indicating_visibility_violation(method_name, visibility))
568
-
569
- expect { double.send(method_name) }.not_to raise_error
570
- expect { double.__send__(method_name) }.not_to raise_error
571
-
572
- unless double.null_object?
573
- # Null object doubles use `method_missing` and so the singleton class
574
- # doesn't know what methods are defined.
575
- singleton_class = class << double; self; end
576
- expect(singleton_class.send("#{visibility}_method_defined?", method_name)).to be true
577
- end
578
- end
579
-
580
- RSpec::Matchers.define :a_message_indicating_visibility_violation do |method_name, visibility|
581
- match do |msg|
582
- # This should NOT Be just `msg.match(visibility)` because the method being called
583
- # has the visibility name in it. We want to ensure it's a message that ruby is
584
- # stating is of the given visibility.
585
- msg.match("#{visibility} ") && msg.match(method_name.to_s)
586
- end
587
- end
588
- end
589
- end
590
- end