rspec-mocks 2.99.4 → 3.0.0.beta1

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.
Files changed (133) hide show
  1. checksums.yaml +14 -6
  2. checksums.yaml.gz.sig +2 -0
  3. data.tar.gz.sig +1 -0
  4. data/Changelog.md +89 -105
  5. data/License.txt +1 -0
  6. data/README.md +77 -57
  7. data/features/argument_matchers/explicit.feature +5 -5
  8. data/features/argument_matchers/general_matchers.feature +10 -10
  9. data/features/argument_matchers/type_matchers.feature +3 -3
  10. data/features/message_expectations/allow_any_instance_of.feature +1 -1
  11. data/features/message_expectations/any_instance.feature +27 -5
  12. data/features/message_expectations/call_original.feature +2 -2
  13. data/features/message_expectations/expect_message_using_expect.feature +2 -2
  14. data/features/message_expectations/expect_message_using_should_receive.feature +2 -2
  15. data/features/message_expectations/receive_counts.feature +7 -7
  16. data/features/message_expectations/warn_when_expectation_is_set_on_nil.feature +3 -3
  17. data/features/method_stubs/README.md +3 -0
  18. data/features/method_stubs/any_instance.feature +11 -11
  19. data/features/method_stubs/as_null_object.feature +4 -4
  20. data/features/method_stubs/simple_return_value_with_stub.feature +7 -7
  21. data/features/method_stubs/stub_chain.feature +3 -3
  22. data/features/method_stubs/stub_implementation.feature +2 -2
  23. data/features/method_stubs/to_ary.feature +2 -2
  24. data/features/mutating_constants/hiding_defined_constant.feature +2 -2
  25. data/features/mutating_constants/stub_defined_constant.feature +5 -5
  26. data/features/mutating_constants/stub_undefined_constant.feature +6 -6
  27. data/features/outside_rspec/configuration.feature +0 -2
  28. data/features/outside_rspec/standalone.feature +1 -1
  29. data/features/spies/spy_partial_mock_method.feature +2 -2
  30. data/features/spies/spy_pure_mock_method.feature +5 -5
  31. data/features/spies/spy_unstubbed_method.feature +1 -1
  32. data/features/support/env.rb +10 -1
  33. data/features/test_frameworks/test_unit.feature +1 -1
  34. data/features/verifying_doubles/class_doubles.feature +88 -0
  35. data/features/verifying_doubles/dynamic_classes.feature +72 -0
  36. data/features/verifying_doubles/introduction.feature +85 -0
  37. data/features/verifying_doubles/object_doubles.feature +65 -0
  38. data/features/verifying_doubles/partial_doubles.feature +34 -0
  39. data/lib/rspec/mocks.rb +8 -34
  40. data/lib/rspec/mocks/any_instance/chain.rb +4 -34
  41. data/lib/rspec/mocks/any_instance/expectation_chain.rb +14 -4
  42. data/lib/rspec/mocks/any_instance/message_chains.rb +27 -12
  43. data/lib/rspec/mocks/any_instance/recorder.rb +23 -31
  44. data/lib/rspec/mocks/any_instance/stub_chain.rb +9 -4
  45. data/lib/rspec/mocks/argument_list_matcher.rb +8 -1
  46. data/lib/rspec/mocks/argument_matchers.rb +26 -12
  47. data/lib/rspec/mocks/arity_calculator.rb +66 -0
  48. data/lib/rspec/mocks/configuration.rb +42 -14
  49. data/lib/rspec/mocks/error_generator.rb +34 -10
  50. data/lib/rspec/mocks/example_methods.rb +64 -19
  51. data/lib/rspec/mocks/extensions/marshal.rb +0 -15
  52. data/lib/rspec/mocks/framework.rb +4 -4
  53. data/lib/rspec/mocks/instance_method_stasher.rb +80 -62
  54. data/lib/rspec/mocks/matchers/have_received.rb +18 -14
  55. data/lib/rspec/mocks/matchers/receive.rb +29 -7
  56. data/lib/rspec/mocks/matchers/receive_messages.rb +72 -0
  57. data/lib/rspec/mocks/message_expectation.rb +95 -148
  58. data/lib/rspec/mocks/method_double.rb +77 -139
  59. data/lib/rspec/mocks/method_reference.rb +95 -0
  60. data/lib/rspec/mocks/mock.rb +1 -1
  61. data/lib/rspec/mocks/mutate_const.rb +12 -9
  62. data/lib/rspec/mocks/object_reference.rb +90 -0
  63. data/lib/rspec/mocks/order_group.rb +49 -7
  64. data/lib/rspec/mocks/proxy.rb +72 -33
  65. data/lib/rspec/mocks/proxy_for_nil.rb +2 -2
  66. data/lib/rspec/mocks/space.rb +13 -18
  67. data/lib/rspec/mocks/stub_chain.rb +2 -2
  68. data/lib/rspec/mocks/syntax.rb +61 -36
  69. data/lib/rspec/mocks/targets.rb +40 -19
  70. data/lib/rspec/mocks/test_double.rb +12 -56
  71. data/lib/rspec/mocks/verifying_double.rb +77 -0
  72. data/lib/rspec/mocks/verifying_message_expecation.rb +60 -0
  73. data/lib/rspec/mocks/verifying_proxy.rb +151 -0
  74. data/lib/rspec/mocks/version.rb +1 -1
  75. data/spec/rspec/mocks/and_call_original_spec.rb +34 -30
  76. data/spec/rspec/mocks/and_yield_spec.rb +2 -2
  77. data/spec/rspec/mocks/any_instance/message_chains_spec.rb +1 -1
  78. data/spec/rspec/mocks/any_instance_spec.rb +53 -260
  79. data/spec/rspec/mocks/argument_expectation_spec.rb +4 -4
  80. data/spec/rspec/mocks/arity_calculator_spec.rb +95 -0
  81. data/spec/rspec/mocks/array_including_matcher_spec.rb +41 -0
  82. data/spec/rspec/mocks/at_least_spec.rb +4 -32
  83. data/spec/rspec/mocks/block_return_value_spec.rb +4 -135
  84. data/spec/rspec/mocks/combining_implementation_instructions_spec.rb +10 -11
  85. data/spec/rspec/mocks/configuration_spec.rb +79 -0
  86. data/spec/rspec/mocks/double_spec.rb +10 -78
  87. data/spec/rspec/mocks/extensions/marshal_spec.rb +0 -8
  88. data/spec/rspec/mocks/failing_argument_matchers_spec.rb +49 -4
  89. data/spec/rspec/mocks/instance_method_stasher_spec.rb +20 -3
  90. data/spec/rspec/mocks/matchers/have_received_spec.rb +74 -0
  91. data/spec/rspec/mocks/matchers/receive_messages_spec.rb +140 -0
  92. data/spec/rspec/mocks/matchers/receive_spec.rb +82 -42
  93. data/spec/rspec/mocks/methods_spec.rb +1 -1
  94. data/spec/rspec/mocks/{bug_report_830_spec.rb → mock_expectation_error_spec.rb} +4 -3
  95. data/spec/rspec/mocks/mock_ordering_spec.rb +11 -0
  96. data/spec/rspec/mocks/mock_space_spec.rb +10 -1
  97. data/spec/rspec/mocks/mock_spec.rb +26 -82
  98. data/spec/rspec/mocks/multiple_return_value_spec.rb +1 -1
  99. data/spec/rspec/mocks/mutate_const_spec.rb +18 -5
  100. data/spec/rspec/mocks/null_object_mock_spec.rb +6 -4
  101. data/spec/rspec/mocks/options_hash_spec.rb +3 -3
  102. data/spec/rspec/mocks/order_group_spec.rb +27 -0
  103. data/spec/rspec/mocks/partial_mock_spec.rb +101 -1
  104. data/spec/rspec/mocks/passing_argument_matchers_spec.rb +3 -20
  105. data/spec/rspec/mocks/record_messages_spec.rb +4 -4
  106. data/spec/rspec/mocks/serialization_spec.rb +4 -6
  107. data/spec/rspec/mocks/space_spec.rb +3 -3
  108. data/spec/rspec/mocks/stub_chain_spec.rb +0 -12
  109. data/spec/rspec/mocks/stub_spec.rb +23 -44
  110. data/spec/rspec/mocks/test_double_spec.rb +3 -22
  111. data/spec/rspec/mocks/verifying_double_spec.rb +327 -0
  112. data/spec/rspec/mocks/verifying_message_expecation_spec.rb +68 -0
  113. data/spec/rspec/mocks_spec.rb +16 -39
  114. data/spec/spec_helper.rb +29 -18
  115. metadata +131 -86
  116. metadata.gz.sig +1 -0
  117. data/features/message_expectations/expect_any_instance_of.feature +0 -27
  118. data/lib/rspec/mocks/caller_filter.rb +0 -60
  119. data/lib/rspec/mocks/deprecation.rb +0 -26
  120. data/lib/rspec/mocks/extensions/instance_exec.rb +0 -34
  121. data/lib/rspec/mocks/extensions/proc.rb +0 -63
  122. data/lib/spec/mocks.rb +0 -4
  123. data/spec/rspec/mocks/and_return_spec.rb +0 -17
  124. data/spec/rspec/mocks/any_number_of_times_spec.rb +0 -36
  125. data/spec/rspec/mocks/before_all_spec.rb +0 -74
  126. data/spec/rspec/mocks/bug_report_10260_spec.rb +0 -8
  127. data/spec/rspec/mocks/bug_report_10263_spec.rb +0 -27
  128. data/spec/rspec/mocks/bug_report_11545_spec.rb +0 -32
  129. data/spec/rspec/mocks/bug_report_496_spec.rb +0 -17
  130. data/spec/rspec/mocks/bug_report_600_spec.rb +0 -22
  131. data/spec/rspec/mocks/bug_report_7611_spec.rb +0 -16
  132. data/spec/rspec/mocks/bug_report_8165_spec.rb +0 -31
  133. data/spec/rspec/mocks/bug_report_957_spec.rb +0 -22
@@ -28,21 +28,21 @@ Feature: stub a chain of methods
28
28
  context "given symbols representing methods" do
29
29
  it "returns the correct value" do
30
30
  subject.stub_chain(:one, :two, :three).and_return(:four)
31
- subject.one.two.three.should eq(:four)
31
+ expect(subject.one.two.three).to eq(:four)
32
32
  end
33
33
  end
34
34
 
35
35
  context "given a hash at the end" do
36
36
  it "returns the correct value" do
37
37
  subject.stub_chain(:one, :two, :three => :four)
38
- subject.one.two.three.should eq(:four)
38
+ expect(subject.one.two.three).to eq(:four)
39
39
  end
40
40
  end
41
41
 
42
42
  context "given a string of methods separated by dots" do
43
43
  it "returns the correct value" do
44
44
  subject.stub_chain("one.two.three").and_return(:four)
45
- subject.one.two.three.should eq(:four)
45
+ expect(subject.one.two.three).to eq(:four)
46
46
  end
47
47
  end
48
48
  end
@@ -39,8 +39,8 @@ Feature: stub with substitute implementation
39
39
  end
40
40
  end
41
41
 
42
- object.foo(:this).should eq("got this")
43
- object.foo(:that).should eq("got that")
42
+ expect(object.foo(:this)).to eq("got this")
43
+ expect(object.foo(:that)).to eq("got that")
44
44
  end
45
45
  end
46
46
  """
@@ -19,12 +19,12 @@ Feature: double handling to_ary
19
19
  shared_examples "to_ary" do
20
20
  it "can be overridden with a stub" do
21
21
  obj.stub(:to_ary) { :non_nil_value }
22
- obj.to_ary.should be(:non_nil_value)
22
+ expect(obj.to_ary).to be(:non_nil_value)
23
23
  end
24
24
 
25
25
  it "supports Array#flatten" do
26
26
  obj = double('foo')
27
- [obj].flatten.should eq([obj])
27
+ expect([obj].flatten).to eq([obj])
28
28
  end
29
29
  end
30
30
 
@@ -14,7 +14,7 @@ Feature: Hide Defined Constant
14
14
  end
15
15
 
16
16
  it "restores the hidden constant when the example completes" do
17
- FOO.should eq(7)
17
+ expect(FOO).to eq(7)
18
18
  end
19
19
  end
20
20
  """
@@ -38,7 +38,7 @@ Feature: Hide Defined Constant
38
38
  end
39
39
 
40
40
  it "restores the hidden constant when the example completes" do
41
- MyGem::SomeClass::FOO.should eq(7)
41
+ expect(MyGem::SomeClass::FOO).to eq(7)
42
42
  end
43
43
  end
44
44
  end
@@ -12,11 +12,11 @@ Feature: Stub Defined Constant
12
12
  describe "stubbing FOO" do
13
13
  it "can stub FOO with a different value" do
14
14
  stub_const("FOO", 5)
15
- FOO.should eq(5)
15
+ expect(FOO).to eq(5)
16
16
  end
17
17
 
18
18
  it "restores the stubbed constant when the example completes" do
19
- FOO.should eq(7)
19
+ expect(FOO).to eq(7)
20
20
  end
21
21
  end
22
22
  """
@@ -36,7 +36,7 @@ Feature: Stub Defined Constant
36
36
  describe SomeClass do
37
37
  it "stubs the nested constant when it is fully qualified" do
38
38
  stub_const("MyGem::SomeClass::FOO", 5)
39
- SomeClass::FOO.should eq(5)
39
+ expect(SomeClass::FOO).to eq(5)
40
40
  end
41
41
  end
42
42
  end
@@ -64,12 +64,12 @@ Feature: Stub Defined Constant
64
64
 
65
65
  it "transfers nested constants when using :transfer_nested_constants => true" do
66
66
  stub_const("MyGem::SomeClass", fake_class, :transfer_nested_constants => true)
67
- SomeClass::FOO.should eq(7)
67
+ expect(SomeClass::FOO).to eq(7)
68
68
  end
69
69
 
70
70
  it "can specify a list of nested constants to transfer" do
71
71
  stub_const("MyGem::SomeClass", fake_class, :transfer_nested_constants => [:FOO])
72
- SomeClass::FOO.should eq(7)
72
+ expect(SomeClass::FOO).to eq(7)
73
73
  end
74
74
  end
75
75
  end
@@ -11,7 +11,7 @@ Feature: Stub Undefined Constant
11
11
  describe "stubbing FOO" do
12
12
  it "can stub undefined constant FOO" do
13
13
  stub_const("FOO", 5)
14
- FOO.should eq(5)
14
+ expect(FOO).to eq(5)
15
15
  end
16
16
 
17
17
  it "undefines the constant when the example completes" do
@@ -33,15 +33,15 @@ Feature: Stub Undefined Constant
33
33
  module MyGem
34
34
  describe SomeClass do
35
35
  it "can stub an arbitrarily deep constant that is undefined" do
36
- defined?(SomeClass::A).should be_false
36
+ expect(defined?(SomeClass::A)).to be_falsey
37
37
  stub_const("MyGem::SomeClass::A::B::C", 3)
38
- SomeClass::A::B::C.should eq(3)
39
- SomeClass::A.should be_a(Module)
38
+ expect(SomeClass::A::B::C).to eq(3)
39
+ expect(SomeClass::A).to be_a(Module)
40
40
  end
41
41
 
42
42
  it 'undefines the intermediary constants that were dynamically created' do
43
- defined?(SomeClass).should be_true
44
- defined?(SomeClass::A).should be_false
43
+ expect(defined?(SomeClass)).to be_truthy
44
+ expect(defined?(SomeClass::A)).to be_falsey
45
45
  end
46
46
  end
47
47
  end
@@ -34,8 +34,6 @@ Feature: configure any test framework to use rspec-mocks
34
34
  example.init
35
35
 
36
36
  puts example.respond_to?(:double)
37
- puts example.respond_to?(:mock)
38
- puts example.respond_to?(:stub)
39
37
  """
40
38
 
41
39
  When I run `ruby foo.rb`
@@ -22,7 +22,7 @@ Feature: standalone
22
22
  require "rspec/mocks/standalone"
23
23
 
24
24
  greeter = double("greeter")
25
- greeter.should_receive(:say_hi)
25
+ expect(greeter).to receive(:say_hi)
26
26
 
27
27
  RSpec::Mocks.verify
28
28
  """
@@ -11,7 +11,7 @@ Feature: Spy on a stubbed method on a partial mock
11
11
  invitation = Object.new
12
12
  invitation.stub(:deliver => true)
13
13
  invitation.deliver
14
- invitation.should have_received(:deliver)
14
+ expect(invitation).to have_received(:deliver)
15
15
  end
16
16
  end
17
17
  """
@@ -25,7 +25,7 @@ Feature: Spy on a stubbed method on a partial mock
25
25
  it "fails when the expectation is not met" do
26
26
  invitation = Object.new
27
27
  invitation.stub(:deliver => true)
28
- invitation.should have_received(:deliver)
28
+ expect(invitation).to have_received(:deliver)
29
29
  end
30
30
  end
31
31
  """
@@ -10,7 +10,7 @@ Feature: Spy on a stubbed method on a pure mock
10
10
  it "passes when the expectation is met" do
11
11
  invitation = double('invitation', :deliver => true)
12
12
  invitation.deliver
13
- invitation.should have_received(:deliver)
13
+ expect(invitation).to have_received(:deliver)
14
14
  end
15
15
  end
16
16
  """
@@ -24,7 +24,7 @@ Feature: Spy on a stubbed method on a pure mock
24
24
  it "passes when the expectation is met" do
25
25
  invitation = double('invitation', :deliver => true)
26
26
  2.times { invitation.deliver(:expected, :arguments) }
27
- invitation.should have_received(:deliver).
27
+ expect(invitation).to have_received(:deliver).
28
28
  with(:expected, :arguments).
29
29
  twice
30
30
  end
@@ -39,7 +39,7 @@ Feature: Spy on a stubbed method on a pure mock
39
39
  describe "have_received" do
40
40
  it "fails when the expectation is not met" do
41
41
  invitation = double('invitation', :deliver => true)
42
- invitation.should have_received(:deliver)
42
+ expect(invitation).to have_received(:deliver)
43
43
  end
44
44
  end
45
45
  """
@@ -54,7 +54,7 @@ Feature: Spy on a stubbed method on a pure mock
54
54
  it "fails when the arguments are different" do
55
55
  invitation = double('invitation', :deliver => true)
56
56
  invitation.deliver(:unexpected)
57
- invitation.should have_received(:deliver).with(:expected, :arguments)
57
+ expect(invitation).to have_received(:deliver).with(:expected, :arguments)
58
58
  end
59
59
  end
60
60
  """
@@ -66,7 +66,7 @@ Feature: Spy on a stubbed method on a pure mock
66
66
  Given a file named "spy_message_spec.rb" with:
67
67
  """ruby
68
68
  describe "have_received" do
69
- subject(:invitation) { double('invitation', :deliver => true) }
69
+ subject(:invitation) { double('invitation', :deliver => true) }
70
70
  before { invitation.deliver }
71
71
 
72
72
  it { should have_received(:deliver) }
@@ -10,7 +10,7 @@ Feature: Spy on an unstubbed method
10
10
  it "raises a helpful error for unstubbed methods" do
11
11
  object = Object.new
12
12
  object.object_id
13
- object.should have_received(:object_id)
13
+ expect(object).to have_received(:object_id)
14
14
  end
15
15
  end
16
16
  """
@@ -2,7 +2,11 @@ require 'aruba/cucumber'
2
2
  require 'rspec/expectations'
3
3
 
4
4
  Before do
5
- RUBY_PLATFORM =~ /java/ ? @aruba_timeout_seconds = 60 : @aruba_timeout_seconds = 5
5
+ if RUBY_PLATFORM =~ /java/ || defined?(Rubinius)
6
+ @aruba_timeout_seconds = 60
7
+ else
8
+ @aruba_timeout_seconds = 5
9
+ end
6
10
  end
7
11
 
8
12
  Aruba.configure do |config|
@@ -11,3 +15,8 @@ Aruba.configure do |config|
11
15
  end
12
16
  end if RUBY_PLATFORM == 'java'
13
17
 
18
+ Aruba.configure do |config|
19
+ config.before_cmd do |cmd|
20
+ set_env('RBXOPT', "-Xint=true #{ENV['RBXOPT']}") # disable JIT since these processes are so short lived
21
+ end
22
+ end if defined?(Rubinius)
@@ -40,4 +40,4 @@ Feature: Test::Unit integration
40
40
  When I run `ruby rspec_mocks_test.rb`
41
41
  Then the output should contain "3 tests, 0 assertions, 0 failures, 1 errors" or "3 tests, 0 assertions, 1 failures, 0 errors"
42
42
  And the output should contain "expected: 0 times with any arguments"
43
- And the output should contain "old_message is deprecated. Use message instead."
43
+ And the output should contain "old_message is deprecated"
@@ -0,0 +1,88 @@
1
+ Feature: Using a class double
2
+
3
+ `class_double` is provided as a complement to `instance_double`, with the
4
+ difference that it verifies class methods on the given class rather than
5
+ instance methods.
6
+
7
+ In addition, it also provides a convenience method `as_stubbed_const` to
8
+ replace concrete classes with the defined double. See [mutating
9
+ constants](../mutating-constants) for more details.
10
+
11
+ Note: `class_double` can be used for modules as well. We chose to stick with
12
+ the `class_double` terminology because the methods a `class_double` verifies
13
+ against are commonly called "class methods", not "module methods", even when
14
+ working with a module.
15
+
16
+ Background:
17
+ Given a file named "lib/user.rb" with:
18
+ """ruby
19
+ class User
20
+ def suspend!
21
+ ConsoleNotifier.notify("suspended as")
22
+ end
23
+ end
24
+ """
25
+
26
+ Given a file named "lib/console_notifier.rb" with:
27
+ """ruby
28
+ class ConsoleNotifier
29
+ MAX_WIDTH = 80
30
+
31
+ def self.notify(message)
32
+ puts message
33
+ end
34
+ end
35
+ """
36
+
37
+ Given a file named "spec/user_spec.rb" with:
38
+ """ruby
39
+ require 'user'
40
+ require 'console_notifier'
41
+
42
+ describe User, '#suspend!' do
43
+ it 'notifies the console' do
44
+ notifier = class_double("ConsoleNotifier").
45
+ as_stubbed_const(:transfer_nested_constants => true)
46
+
47
+ expect(notifier).to receive(:notify).with("suspended as")
48
+ expect(ConsoleNotifier::MAX_WIDTH).to eq(80)
49
+
50
+ user = User.new
51
+ user.suspend!
52
+ end
53
+ end
54
+ """
55
+
56
+ Scenario: replacing existing constants
57
+ When I run `rspec spec/user_spec.rb`
58
+ Then the examples should all pass
59
+
60
+ Scenario: renaming `ConsoleNotifier.notify` to `send_notification`
61
+ Given a file named "lib/console_notifier.rb" with:
62
+ """ruby
63
+ class ConsoleNotifier
64
+ MAX_WIDTH = 80
65
+
66
+ def self.send_notification(message)
67
+ puts message
68
+ end
69
+ end
70
+ """
71
+ When I run `rspec spec/user_spec.rb`
72
+ Then the output should contain "1 example, 1 failure"
73
+ And the output should contain "ConsoleNotifier does not implement:"
74
+
75
+ Scenario: adding `color` as a second argument to `ConsoleNotifier.notify`
76
+ Given a file named "lib/console_notifier.rb" with:
77
+ """ruby
78
+ class ConsoleNotifier
79
+ MAX_WIDTH = 80
80
+
81
+ def self.notify(message, color)
82
+ puts color + message
83
+ end
84
+ end
85
+ """
86
+ When I run `rspec spec/user_spec.rb`
87
+ Then the output should contain "1 example, 1 failure"
88
+ And the output should contain "Wrong number of arguments."
@@ -0,0 +1,72 @@
1
+ Feature: Dynamic classes
2
+
3
+ Verifying instance doubles do not support methods which the class reports to
4
+ not exist since an actual instance of the class would be required to verify
5
+ against. This is commonly the case when `method_missing` is used.
6
+ `ActiveRecord` does this to define methods from database columns. If the
7
+ object has already been loaded you may consider using an `object_double`, but
8
+ that cannot work if you are testing in isolation.
9
+
10
+ These types of methods are supported at class level, since `respond_to?` can
11
+ be queried directly on the class.
12
+
13
+
14
+ Background:
15
+ Given a file named "lib/fake_active_record.rb" with:
16
+ """ruby
17
+ class FakeActiveRecord
18
+ COLUMNS = %w[name email]
19
+
20
+ def respond_to_missing?(method_name)
21
+ COLUMNS.include?(method_name.to_s) || super
22
+ end
23
+
24
+ def method_missing(method_name, *args)
25
+ if respond_to?(method_name)
26
+ instance_variable_get("@#{method_name}")
27
+ else
28
+ super
29
+ end
30
+ end
31
+ end
32
+ """
33
+
34
+ Given a file named "spec/user_spec.rb" with:
35
+ """ruby
36
+ require 'user'
37
+
38
+ describe User do
39
+ it 'can be doubled' do
40
+ instance_double("User", :name => "Don")
41
+ end
42
+ end
43
+ """
44
+
45
+ Scenario: fails with method missing
46
+
47
+ Given a file named "lib/user.rb" with:
48
+ """ruby
49
+ require 'fake_active_record'
50
+
51
+ class User < FakeActiveRecord
52
+ end
53
+ """
54
+
55
+ When I run `rspec spec/user_spec.rb`
56
+ Then the output should contain "1 example, 1 failure"
57
+
58
+ Scenario: workaround with explict definitions
59
+
60
+ Given a file named "lib/user.rb" with:
61
+ """ruby
62
+ require 'fake_active_record'
63
+
64
+ class User < FakeActiveRecord
65
+ def name; super end
66
+ def email; super end
67
+ end
68
+ """
69
+
70
+ When I run `rspec spec/user_spec.rb`
71
+ Then the examples should all pass
72
+
@@ -0,0 +1,85 @@
1
+ Feature: Verifying doubles
2
+
3
+ Verifying doubles are a stricter alternative to normal doubles that provide
4
+ guarantees about what is being verified. When using verifying doubles, RSpec
5
+ will check that the methods being stubbed are actually present on the
6
+ underlying object if it is available. Prefer using veryifing doubles over
7
+ normal doubles.
8
+
9
+ No checking will happen if the constant name is not defined, but when run
10
+ with the constant present (either as a full spec run or by explicitly
11
+ preloading collaborators) a failure will be triggered if an invalid method is
12
+ being stubbed.
13
+
14
+ This dual approach allows you to move very quickly and test components in
15
+ isolation, while giving you confidence that your doubles are not a complete
16
+ fiction. Testing in isolation is optional but recommend for classes that do
17
+ not depend on third-party components.
18
+
19
+ Background:
20
+ Given a file named "app/models/user.rb" with:
21
+ """ruby
22
+ class User < Struct.new(:notifier)
23
+ def suspend!
24
+ notifier.notify("suspended as")
25
+ end
26
+ end
27
+ """
28
+
29
+ Given a file named "app/models/console_notifier.rb" with:
30
+ """ruby
31
+ class ConsoleNotifier
32
+ # notify is not defined yet.
33
+ end
34
+ """
35
+
36
+ Given a file named "spec/unit_helper.rb" with:
37
+ """ruby
38
+ $LOAD_PATH.unshift("app/models")
39
+ """
40
+
41
+ Given a file named "spec/spec_helper.rb" with:
42
+ """ruby
43
+ require 'unit_helper'
44
+
45
+ require 'user'
46
+ require 'console_notifier'
47
+
48
+ RSpec.configure do |config|
49
+ config.mock_with :rspec do |mocks|
50
+
51
+ # This option should be set when all dependencies are being loaded
52
+ # before a spec run, as is the case in a typical spec helper. It will
53
+ # cause any verifying double instantiation for a class that does not
54
+ # exist to raise, protecting against incorrectly spelt names.
55
+ mocks.verify_doubled_constant_names = true
56
+
57
+ end
58
+ end
59
+ """
60
+
61
+ Given a file named "spec/unit/user_spec.rb" with:
62
+ """ruby
63
+ require 'unit_helper'
64
+
65
+ require 'user'
66
+
67
+ describe User, '#suspend!' do
68
+ it 'notifies the console' do
69
+ notifier = instance_double("ConsoleNotifier")
70
+
71
+ expect(notifier).to receive(:notify).with("suspended as")
72
+
73
+ user = User.new(notifier)
74
+ user.suspend!
75
+ end
76
+ end
77
+ """
78
+
79
+ Scenario: spec passes in isolation
80
+ When I run `rspec spec/unit/user_spec.rb`
81
+ Then the examples should all pass
82
+
83
+ Scenario: spec fails with dependencies loaded
84
+ When I run `rspec -r./spec/spec_helper spec/unit/user_spec.rb`
85
+ Then the output should contain "1 example, 1 failure"