bogus 0.0.2 → 0.0.3.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile.lock +14 -2
  3. data/Guardfile +5 -0
  4. data/README.md +7 -249
  5. data/bogus.gemspec +3 -1
  6. data/features/.nav +21 -0
  7. data/features/authors.md +42 -0
  8. data/{CHANGELOG.md → features/changelog.md} +9 -2
  9. data/features/configuration_options.feature +1 -2
  10. data/features/{contract_tests_mocks.feature → contract_tests/contract_tests_mocks.feature} +4 -1
  11. data/features/{contract_tests_spies.feature → contract_tests/contract_tests_spies.feature} +2 -0
  12. data/features/{contract_tests_stubs.feature → contract_tests/contract_tests_stubs.feature} +14 -0
  13. data/features/contract_tests/readme.md +26 -0
  14. data/features/{return_value_contracts.feature → contract_tests/return_value_contracts.feature} +6 -2
  15. data/features/{anonymous_doubles.feature → fakes/anonymous_doubles.feature} +24 -8
  16. data/features/{fake_objects.feature → fakes/fake_objects.feature} +39 -4
  17. data/features/fakes/global_fake_configuration.feature +88 -0
  18. data/features/fakes/readme.md +11 -0
  19. data/features/fakes/replacing_classes.feature +148 -0
  20. data/features/getting_started.md +36 -0
  21. data/features/license.md +9 -0
  22. data/features/readme.md +173 -0
  23. data/features/safe_stubbing/argument_matchers.feature +30 -0
  24. data/features/safe_stubbing/readme.md +35 -0
  25. data/features/{safe_mocking.feature → safe_stubbing/safe_mocking.feature} +14 -0
  26. data/features/{safe_stubbing.feature → safe_stubbing/safe_stubbing.feature} +18 -4
  27. data/features/{spies.feature → safe_stubbing/spies.feature} +19 -4
  28. data/features/step_definitions/rspec_steps.rb +14 -5
  29. data/features/support/env.rb +4 -0
  30. data/lib/bogus.rb +2 -0
  31. data/lib/bogus/adds_recording.rb +11 -7
  32. data/lib/bogus/any_args.rb +7 -0
  33. data/lib/bogus/anything.rb +11 -0
  34. data/lib/bogus/contract_not_fulfilled.rb +17 -10
  35. data/lib/bogus/copies_classes.rb +2 -6
  36. data/lib/bogus/creates_fakes_with_stubbed_methods.rb +40 -0
  37. data/lib/bogus/double.rb +28 -8
  38. data/lib/bogus/ensures_all_interactions_satisfied.rb +36 -0
  39. data/lib/bogus/fake.rb +6 -0
  40. data/lib/bogus/fake_configuration.rb +69 -0
  41. data/lib/bogus/fakes_classes.rb +21 -0
  42. data/lib/bogus/has_overwritten_methods.rb +24 -0
  43. data/lib/bogus/have_received_matcher.rb +63 -0
  44. data/lib/bogus/injector.rb +36 -14
  45. data/lib/bogus/interaction.rb +33 -17
  46. data/lib/bogus/makes_substitute_methods.rb +15 -0
  47. data/lib/bogus/mocking_dsl.rb +31 -0
  48. data/lib/bogus/multi_stubber.rb +15 -0
  49. data/lib/bogus/not_all_expectations_satisfied.rb +27 -0
  50. data/lib/bogus/overwriten_classes.rb +15 -0
  51. data/lib/bogus/overwrites_classes.rb +2 -2
  52. data/lib/bogus/overwrites_methods.rb +42 -0
  53. data/lib/bogus/proxies_method_calls.rb +23 -0
  54. data/lib/bogus/proxy_class.rb +25 -16
  55. data/lib/bogus/public_methods.rb +36 -11
  56. data/lib/bogus/record_interactions.rb +3 -9
  57. data/lib/bogus/recording_proxy.rb +5 -0
  58. data/lib/bogus/registers_created_fakes.rb +2 -1
  59. data/lib/bogus/resets_overwritten_classes.rb +14 -0
  60. data/lib/bogus/resets_stubbed_methods.rb +12 -0
  61. data/lib/bogus/responds_to_everything.rb +11 -0
  62. data/lib/bogus/rspec.rb +7 -0
  63. data/lib/bogus/rspec_adapter.rb +17 -0
  64. data/lib/bogus/rspec_extensions.rb +8 -20
  65. data/lib/bogus/shadow.rb +60 -0
  66. data/lib/bogus/verifies_contracts.rb +5 -1
  67. data/lib/bogus/verifies_stub_definition.rb +5 -0
  68. data/lib/bogus/version.rb +1 -1
  69. data/lib/tracks_existence_of_test_doubles.rb +11 -0
  70. data/spec/bogus/adds_recording_spec.rb +46 -10
  71. data/spec/bogus/anything_spec.rb +13 -0
  72. data/spec/bogus/copies_classes_spec.rb +4 -3
  73. data/spec/bogus/creates_fakes_with_stubbed_methods_spec.rb +121 -0
  74. data/spec/bogus/double_spec.rb +63 -20
  75. data/spec/bogus/ensures_all_interactions_satisfied_spec.rb +43 -0
  76. data/spec/bogus/fake_configuration_spec.rb +99 -0
  77. data/spec/bogus/fakes_classes_spec.rb +46 -0
  78. data/spec/bogus/have_received_matcher_spec.rb +56 -0
  79. data/spec/bogus/interaction_spec.rb +18 -7
  80. data/spec/bogus/interactions_repository_spec.rb +42 -0
  81. data/spec/bogus/makes_substitute_methods_spec.rb +24 -0
  82. data/spec/bogus/mocking_dsl_spec.rb +234 -7
  83. data/spec/bogus/multi_stubber_spec.rb +31 -0
  84. data/spec/bogus/overwriten_classes_spec.rb +27 -0
  85. data/spec/bogus/overwrites_classes_spec.rb +2 -2
  86. data/spec/bogus/overwrites_methods_spec.rb +107 -0
  87. data/spec/bogus/proxy_class_spec.rb +6 -0
  88. data/spec/bogus/record_interactions_spec.rb +3 -4
  89. data/spec/bogus/registers_created_fakes_spec.rb +8 -0
  90. data/spec/bogus/resets_overwritten_classes_spec.rb +26 -0
  91. data/spec/bogus/resets_stubbed_methods_spec.rb +16 -0
  92. data/spec/bogus/shadow_spec.rb +182 -0
  93. data/spec/bogus/verifies_contracts_spec.rb +9 -3
  94. data/spec/bogus/verifies_stub_definition_spec.rb +4 -0
  95. data/spec/spec_helper.rb +3 -0
  96. data/spec/support/fake_creator_of_fakes.rb +15 -0
  97. data/spec/support/sample_fake.rb +13 -0
  98. data/spec/tracks_existence_of_test_doubles_spec.rb +26 -0
  99. metadata +105 -32
  100. data/lib/bogus/creates_anonymous_stubs.rb +0 -27
  101. data/lib/bogus/invocation_matcher.rb +0 -27
  102. data/lib/bogus/rr_proxy.rb +0 -5
  103. data/spec/bogus/invocation_matcher_spec.rb +0 -26
data/lib/bogus/rspec.rb CHANGED
@@ -3,4 +3,11 @@ require 'bogus'
3
3
  RSpec.configure do |config|
4
4
  config.extend Bogus::RSpecExtensions
5
5
  config.include Bogus::MockingDSL
6
+
7
+ config.mock_with Bogus::RSpecAdapter
8
+ config.backtrace_clean_patterns << Regexp.new("lib/bogus")
9
+
10
+ config.after(:suite) do
11
+ Bogus.reset!
12
+ end
6
13
  end
@@ -0,0 +1,17 @@
1
+ module Bogus
2
+ module RSpecAdapter
3
+ def setup_mocks_for_rspec
4
+ # no setup needed
5
+ end
6
+
7
+ def verify_mocks_for_rspec
8
+ Bogus.ensure_all_expectations_satisfied!
9
+ end
10
+
11
+ def teardown_mocks_for_rspec
12
+ Bogus.reset_stubbed_methods
13
+ Bogus.clear_expectations
14
+ Bogus.reset_overwritten_classes
15
+ end
16
+ end
17
+ end
@@ -1,12 +1,18 @@
1
1
  module Bogus
2
2
  module RSpecExtensions
3
3
  def fake(name, opts = {}, &block)
4
- let(name) { Bogus.fake_for(name, opts, &block) }
4
+ let(name) { fake(name, opts, &block) }
5
+ end
6
+
7
+ def fake_class(name, opts = {})
8
+ before do
9
+ fake_class(name, opts)
10
+ end
5
11
  end
6
12
 
7
13
  def verify_contract(name)
8
14
  before do
9
- Bogus.record_calls_for(name)
15
+ Bogus.record_calls_for(name, described_class)
10
16
  end
11
17
 
12
18
  RSpec.configure do |config|
@@ -14,23 +20,5 @@ module Bogus
14
20
  end
15
21
  end
16
22
  end
17
-
18
- module MockingDSL
19
- def fake(*args)
20
- Bogus.create_anonymous_stub(*args)
21
- end
22
-
23
- def stub(*args)
24
- Bogus.create_stub(*args)
25
- end
26
-
27
- def have_received(*args)
28
- Bogus.have_received(*args)
29
- end
30
-
31
- def mock(*args)
32
- Bogus.create_mock(*args)
33
- end
34
- end
35
23
  end
36
24
 
@@ -0,0 +1,60 @@
1
+ module Bogus
2
+ class Shadow
3
+ attr_reader :calls
4
+
5
+ def initialize(&default_return_value)
6
+ @calls = []
7
+ @stubs = []
8
+ @defaults = Hash.new(default_return_value)
9
+ @required = Set.new
10
+ end
11
+
12
+ def run(method_name, *args)
13
+ interaction = Interaction.new(method_name, args)
14
+ @calls << interaction
15
+ return_value(interaction)
16
+ end
17
+
18
+ def has_received(name, args)
19
+ @calls.include?(Interaction.new(name, args))
20
+ end
21
+
22
+ def stubs(name, *args, &return_value)
23
+ interaction = Interaction.new(name, args)
24
+ add_stub(interaction, return_value)
25
+ override_default(interaction, return_value)
26
+ @required.delete(interaction)
27
+ interaction
28
+ end
29
+
30
+ def mocks(name, *args, &return_value)
31
+ interaction = stubs(name, *args, &return_value)
32
+ @required.add(interaction)
33
+ end
34
+
35
+ def unsatisfied_interactions
36
+ @required.to_a - @calls
37
+ end
38
+
39
+ def self.has_shadow?(object)
40
+ object.respond_to?(:__shadow__)
41
+ end
42
+
43
+ private
44
+
45
+ def override_default(interaction, return_value)
46
+ return unless interaction.any_args?
47
+ @defaults[interaction.method] = return_value || proc{nil}
48
+ end
49
+
50
+ def add_stub(interaction, return_value_block)
51
+ @stubs << [interaction, return_value_block] if return_value_block
52
+ end
53
+
54
+ def return_value(interaction)
55
+ _, return_value = @stubs.reverse.find{|i, v| i == interaction}
56
+ return_value ||= @defaults[interaction.method]
57
+ return_value.call
58
+ end
59
+ end
60
+ end
@@ -7,6 +7,10 @@ class Bogus::VerifiesContracts
7
7
  missed = doubled_interactions.for_fake(fake_name).reject do |interaction|
8
8
  real_interactions.recorded?(fake_name, interaction)
9
9
  end
10
- raise Bogus::ContractNotFulfilled.new(fake_name => missed) unless missed.empty?
10
+
11
+ unless missed.empty?
12
+ actual = real_interactions.for_fake(fake_name)
13
+ raise Bogus::ContractNotFulfilled.new(fake_name, missed: missed, actual: actual)
14
+ end
11
15
  end
12
16
  end
@@ -6,6 +6,7 @@ class Bogus::VerifiesStubDefinition
6
6
  def verify!(object, method_name, args)
7
7
  stubbing_non_existent_method!(object, method_name) unless object.respond_to?(method_name)
8
8
  return unless object.methods.include?(method_name)
9
+ return if any_args?(args)
9
10
  method = object.method(method_name)
10
11
  wrong_number_of_arguments!(method, args) if under_number_of_required_arguments?(method, args.size)
11
12
  wrong_number_of_arguments!(method, args) if over_number_of_allowed_arguments?(method, args.size)
@@ -35,4 +36,8 @@ class Bogus::VerifiesStubDefinition
35
36
 
36
37
  args_count > number_of_arguments
37
38
  end
39
+
40
+ def any_args?(args)
41
+ [Bogus::AnyArgs] == args
42
+ end
38
43
  end
data/lib/bogus/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Bogus
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3.rc.1"
3
3
  end
@@ -0,0 +1,11 @@
1
+ module Bogus
2
+ class TracksExistenceOfTestDoubles
3
+ def track(object)
4
+ doubles << object unless doubles.include?(object)
5
+ end
6
+
7
+ def doubles
8
+ @doubles ||= []
9
+ end
10
+ end
11
+ end
@@ -4,30 +4,66 @@ describe Bogus::AddsRecording do
4
4
  module SampleModule
5
5
  class Library
6
6
  end
7
+
8
+ class OtherClass
9
+ end
7
10
  end
8
11
 
9
12
  let(:converts_name_to_class) { stub }
10
13
  let(:create_proxy_class) { stub }
11
14
  let(:overwrites_classes) { stub }
12
- let(:adds_recording) { Bogus::AddsRecording.new(converts_name_to_class, create_proxy_class, overwrites_classes) }
15
+ let(:overwritten_classes) { stub }
16
+
17
+ let(:adds_recording) { isolate(Bogus::AddsRecording) }
13
18
 
14
19
  before do
15
20
  stub(converts_name_to_class).convert { SampleModule::Library }
16
21
  stub(create_proxy_class).call { Object }
17
22
  stub(overwrites_classes).overwrite
18
-
19
- adds_recording.add(:library)
23
+ stub(overwritten_classes).add
20
24
  end
21
25
 
22
- it "converts the fake name to class" do
23
- converts_name_to_class.should have_received.convert(:library)
24
- end
26
+ context "without class argument" do
27
+ before do
28
+ adds_recording.add(:library)
29
+ end
30
+
31
+ it "converts the fake name to class" do
32
+ converts_name_to_class.should have_received.convert(:library)
33
+ end
34
+
35
+ it "creates the proxy" do
36
+ create_proxy_class.should have_received.call(:library, SampleModule::Library)
37
+ end
38
+
39
+ it "swaps the classes" do
40
+ overwrites_classes.should have_received.overwrite('SampleModule::Library', Object)
41
+ end
25
42
 
26
- it "creates the proxy" do
27
- create_proxy_class.should have_received.call(:library, SampleModule::Library)
43
+ it "records the overwritten class, so that it can be later restored" do
44
+ overwritten_classes.should have_received.add("SampleModule::Library", SampleModule::Library)
45
+ end
28
46
  end
29
47
 
30
- it "swaps the classes" do
31
- overwrites_classes.should have_received.overwrite(SampleModule::Library, Object)
48
+ context "with class argument" do
49
+ before do
50
+ adds_recording.add(:library, SampleModule::OtherClass)
51
+ end
52
+
53
+ it "uses the passed class" do
54
+ converts_name_to_class.should_not have_received.convert(:library)
55
+ end
56
+
57
+ it "creates the proxy" do
58
+ create_proxy_class.should have_received.call(:library, SampleModule::OtherClass)
59
+ end
60
+
61
+ it "swaps the classes" do
62
+ overwrites_classes.should have_received.overwrite('SampleModule::OtherClass', Object)
63
+ end
64
+
65
+ it "records the overwritten class, so that it can be later restored" do
66
+ overwritten_classes.should have_received.add("SampleModule::OtherClass", SampleModule::OtherClass)
67
+ end
32
68
  end
33
69
  end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bogus::Anything do
4
+ it "is equal to everything" do
5
+ anything = Bogus::Anything
6
+
7
+ anything.should == "foo"
8
+ anything.should == "bar"
9
+ anything.should == 1
10
+ anything.should == Object.new
11
+ anything.should == anything
12
+ end
13
+ end
@@ -1,4 +1,4 @@
1
- require_relative '../spec_helper'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Bogus::CopiesClasses do
4
4
  module SampleMethods
@@ -57,8 +57,9 @@ describe Bogus::CopiesClasses do
57
57
  end
58
58
  end
59
59
 
60
- let(:method_stringifier) { Bogus::MethodStringifier.new }
61
- let(:copies_classes) { Bogus::CopiesClasses.new(method_stringifier) }
60
+ let(:method_stringifier) { isolate(Bogus::MethodStringifier) }
61
+ let(:makes_substitute_methods) { isolate(Bogus::MakesSubstituteMethods) }
62
+ let(:copies_classes) { isolate(Bogus::CopiesClasses) }
62
63
  let(:fake_class) { copies_classes.copy(klass) }
63
64
  let(:fake) { fake_class.new }
64
65
 
@@ -0,0 +1,121 @@
1
+ require 'spec_helper'
2
+
3
+ module Bogus
4
+ describe CreatesFakesWithStubbedMethods do
5
+ let(:creates_fakes) { FakeCreatorOfFakes.new }
6
+ let(:fake_configuration) { stub }
7
+ let(:responds_to_everything) { stub }
8
+ let(:multi_stubber) { stub(stub_all: :stubbed_object) }
9
+
10
+ let(:creates_anonymous_stubs) { isolate(CreatesFakesWithStubbedMethods) }
11
+
12
+ before do
13
+ stub(fake_configuration).include? { false }
14
+ end
15
+
16
+ context "given symbol as first parameter" do
17
+ let(:fake) { [:foo, {as: :class}, "something"] }
18
+
19
+ before do
20
+ creates_anonymous_stubs.create(:foo, bar: 1, as: :class) { "something" }
21
+ end
22
+
23
+ it "creates fakes" do
24
+ creates_fakes.should have_created(:foo, {as: :class}, "something")
25
+ end
26
+
27
+ it "stubs all the given methods" do
28
+ multi_stubber.should have_received.stub_all(fake, bar: 1)
29
+ end
30
+ end
31
+
32
+ context "given hash as first parameter" do
33
+ before do
34
+ creates_anonymous_stubs.create(bar: 1)
35
+ end
36
+
37
+ it "does not create fakes" do
38
+ creates_fakes.fakes.should == []
39
+ end
40
+
41
+ it "stubs all the given methods" do
42
+ multi_stubber.should have_received.stub_all(responds_to_everything, bar: 1)
43
+ end
44
+ end
45
+
46
+ context "given symbol as only parameter" do
47
+ let(:fake) { [:foo, {}, "something"] }
48
+
49
+ before do
50
+ creates_anonymous_stubs.create(:foo) { "something" }
51
+ end
52
+
53
+ it "creates fakes" do
54
+ creates_fakes.should have_created(:foo, {}, "something")
55
+ end
56
+
57
+ it "stubs all the given methods" do
58
+ multi_stubber.should have_received.stub_all(fake)
59
+ end
60
+ end
61
+
62
+ context "with no parameters" do
63
+ before do
64
+ creates_anonymous_stubs.create
65
+ end
66
+
67
+ it "does not create fakes" do
68
+ creates_fakes.fakes.should == []
69
+ end
70
+
71
+ it "stubs all the given methods" do
72
+ multi_stubber.should have_received.stub_all(responds_to_everything)
73
+ end
74
+ end
75
+
76
+ context "when the fake was globally configured" do
77
+ let(:fake) { [:foo, {as: :class}, "SomeClass"] }
78
+
79
+ before do
80
+ stub(fake_configuration).include?(:foo) { true }
81
+ stub(fake_configuration).get(:foo) { FakeDefinition.new(opts: {as: :class},
82
+ stubs: {xyz: "abc"},
83
+ class_block: proc{"SomeClass"}) }
84
+
85
+ creates_anonymous_stubs.create(:foo)
86
+ end
87
+
88
+ it "uses the configuration to create fake" do
89
+ creates_fakes.fakes.should == [fake]
90
+
91
+ fake_configuration.should have_received.include?(:foo)
92
+ fake_configuration.should have_received.get(:foo)
93
+ end
94
+
95
+ it "stubs the methods defined in configuration" do
96
+ multi_stubber.should have_received.stub_all(fake, xyz: "abc")
97
+ end
98
+ end
99
+
100
+ context "overriding the global configuration" do
101
+ let(:fake) { [:foo, {as: :instance}, "SomeOtherClass"] }
102
+
103
+ before do
104
+ stub(fake_configuration).include?(:foo) { true }
105
+ stub(fake_configuration).get(:foo) { FakeDefinition.new(opts: {as: :class},
106
+ stubs: {a: "b", b: "c"},
107
+ class_block: proc{"SomeClass"}) }
108
+
109
+ creates_anonymous_stubs.create(:foo, as: :instance, b: "d", c: "e") { "SomeOtherClass" }
110
+ end
111
+
112
+ it "overrides the class block and fake options" do
113
+ creates_fakes.should have_created(:foo, {as: :instance}, "SomeOtherClass")
114
+ end
115
+
116
+ it "overrides the stubbed methods" do
117
+ multi_stubber.should have_received.stub_all(fake, a: "b", b: "d", c: "e")
118
+ end
119
+ end
120
+ end
121
+ end
@@ -1,31 +1,74 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Bogus::Double do
4
- let(:rr_double) { stub }
5
- let(:verifies_stub_definition) { stub }
6
- let(:records_double_interactions) { stub }
3
+ module Bogus
4
+ describe Double do
5
+ shared_examples_for "double behavior" do
6
+ it "tracks existence of test doubles" do
7
+ mock(double_tracker).track(object)
7
8
 
8
- let(:object) { "strings have plenty of methods to call" }
9
+ double.stub.foo("a", "b") { "the result" }
10
+ end
9
11
 
10
- let(:bogus_double) { isolate(Bogus::Double, double: rr_double) }
12
+ it "verifies stub definition" do
13
+ mock(verifies_stub_definition).verify!(object, :foo, ["a", "b"])
11
14
 
12
- before do
13
- stub(verifies_stub_definition).verify!
14
- stub(records_double_interactions).record
15
- stub(rr_double).method_name
15
+ double.stub.foo("a", "b") { "the result" }
16
+ end
16
17
 
17
- bogus_double.method_name(:foo, :bar)
18
- end
18
+ it "stubs shadow methods" do
19
+ object.extend RecordInteractions
20
+ mock(object.__shadow__).stubs(:foo, "a", "b")
19
21
 
20
- it "verifies that stub definition matches the real definition" do
21
- verifies_stub_definition.should have_received.verify!(object, :method_name, [:foo, :bar])
22
- end
22
+ double.stub.foo("a", "b") { "the result" }
23
+ end
23
24
 
24
- it "records the stub interaction so that it can be verified later" do
25
- records_double_interactions.should have_received.record(object, :method_name, [:foo, :bar])
26
- end
25
+ it "mocks shadow methods" do
26
+ object.extend RecordInteractions
27
+ mock(object.__shadow__).mocks(:foo, "a", "b")
28
+
29
+ double.mock.foo("a", "b") { "the result" }
30
+ end
31
+
32
+ it "adds method overwriting" do
33
+ double.stub.foo("a", "b") { "the result" }
34
+
35
+ overwrites_methods.overwrites.should == [[object, :foo]]
36
+ end
37
+
38
+ it "records double interactions" do
39
+ mock(records_double_interactions).record(object, :foo, ["a", "b"])
40
+
41
+ double.stub.foo("a", "b") { "the result" }
42
+ end
43
+ end
44
+
45
+ let(:double_tracker) { stub(track: nil) }
46
+ let(:verifies_stub_definition) { stub(verify!: nil) }
47
+ let(:records_double_interactions) { stub(record: nil) }
48
+ let(:overwrites_methods) { FakeMethodOverwriter.new }
49
+ let(:double) { isolate(Double) }
50
+
51
+ context "with regular objects" do
52
+ let(:object) { Samples::Foo.new }
53
+
54
+ include_examples "double behavior"
55
+ end
56
+
57
+ context "with fakes" do
58
+ let(:object) { Samples::FooFake.new }
59
+
60
+ include_examples "double behavior"
61
+ end
62
+
63
+ class FakeMethodOverwriter
64
+ def overwrite(object, method)
65
+ overwrites << [object, method]
66
+ object.extend RecordInteractions
67
+ end
27
68
 
28
- it "proxies the method call" do
29
- rr_double.should have_received.method_name(:foo, :bar)
69
+ def overwrites
70
+ @overwrites ||= []
71
+ end
72
+ end
30
73
  end
31
74
  end