rspec-mocks 2.99.4 → 3.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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"