mcmire-rr 1.0.5.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. data/CHANGES +269 -0
  2. data/Gemfile +16 -0
  3. data/Gemfile.lock +47 -0
  4. data/LICENSE +22 -0
  5. data/README.rdoc +390 -0
  6. data/Rakefile +49 -0
  7. data/VERSION +1 -0
  8. data/lib/rr.rb +101 -0
  9. data/lib/rr/adapters/minitest.rb +31 -0
  10. data/lib/rr/adapters/rr_methods.rb +146 -0
  11. data/lib/rr/adapters/rspec.rb +61 -0
  12. data/lib/rr/adapters/rspec2.rb +22 -0
  13. data/lib/rr/adapters/test_unit.rb +31 -0
  14. data/lib/rr/blank_slate.rb +17 -0
  15. data/lib/rr/class_instance_method_defined.rb +9 -0
  16. data/lib/rr/double.rb +154 -0
  17. data/lib/rr/double_definitions/child_double_definition_create.rb +27 -0
  18. data/lib/rr/double_definitions/double_definition.rb +365 -0
  19. data/lib/rr/double_definitions/double_definition_create.rb +139 -0
  20. data/lib/rr/double_definitions/double_definition_create_blank_slate.rb +26 -0
  21. data/lib/rr/double_definitions/double_injections/any_instance_of.rb +28 -0
  22. data/lib/rr/double_definitions/double_injections/instance.rb +16 -0
  23. data/lib/rr/double_definitions/strategies/double_injection/any_instance_of.rb +30 -0
  24. data/lib/rr/double_definitions/strategies/double_injection/double_injection_strategy.rb +10 -0
  25. data/lib/rr/double_definitions/strategies/double_injection/instance.rb +17 -0
  26. data/lib/rr/double_definitions/strategies/implementation/implementation_strategy.rb +10 -0
  27. data/lib/rr/double_definitions/strategies/implementation/proxy.rb +60 -0
  28. data/lib/rr/double_definitions/strategies/implementation/reimplementation.rb +14 -0
  29. data/lib/rr/double_definitions/strategies/implementation/strongly_typed_reimplementation.rb +15 -0
  30. data/lib/rr/double_definitions/strategies/strategy.rb +43 -0
  31. data/lib/rr/double_definitions/strategies/strategy_methods.rb +53 -0
  32. data/lib/rr/double_definitions/strategies/verification/dont_allow.rb +31 -0
  33. data/lib/rr/double_definitions/strategies/verification/mock.rb +42 -0
  34. data/lib/rr/double_definitions/strategies/verification/stub.rb +43 -0
  35. data/lib/rr/double_definitions/strategies/verification/verification_strategy.rb +10 -0
  36. data/lib/rr/double_matches.rb +42 -0
  37. data/lib/rr/errors/argument_equality_error.rb +6 -0
  38. data/lib/rr/errors/double_definition_error.rb +6 -0
  39. data/lib/rr/errors/double_not_found_error.rb +6 -0
  40. data/lib/rr/errors/double_order_error.rb +6 -0
  41. data/lib/rr/errors/rr_error.rb +20 -0
  42. data/lib/rr/errors/spy_verification_errors/double_injection_not_found_error.rb +8 -0
  43. data/lib/rr/errors/spy_verification_errors/invocation_count_error.rb +8 -0
  44. data/lib/rr/errors/spy_verification_errors/spy_verification_error.rb +8 -0
  45. data/lib/rr/errors/subject_does_not_implement_method_error.rb +6 -0
  46. data/lib/rr/errors/subject_has_different_arity_error.rb +6 -0
  47. data/lib/rr/errors/times_called_error.rb +6 -0
  48. data/lib/rr/expectations/any_argument_expectation.rb +21 -0
  49. data/lib/rr/expectations/argument_equality_expectation.rb +41 -0
  50. data/lib/rr/expectations/times_called_expectation.rb +57 -0
  51. data/lib/rr/hash_with_object_id_key.rb +46 -0
  52. data/lib/rr/injections/double_injection.rb +220 -0
  53. data/lib/rr/injections/injection.rb +33 -0
  54. data/lib/rr/injections/method_missing_injection.rb +73 -0
  55. data/lib/rr/injections/singleton_method_added_injection.rb +72 -0
  56. data/lib/rr/method_dispatches/base_method_dispatch.rb +84 -0
  57. data/lib/rr/method_dispatches/method_dispatch.rb +59 -0
  58. data/lib/rr/method_dispatches/method_missing_dispatch.rb +61 -0
  59. data/lib/rr/proc_from_block.rb +7 -0
  60. data/lib/rr/recorded_calls.rb +103 -0
  61. data/lib/rr/space.rb +119 -0
  62. data/lib/rr/spy_verification.rb +48 -0
  63. data/lib/rr/spy_verification_proxy.rb +13 -0
  64. data/lib/rr/times_called_matchers/any_times_matcher.rb +18 -0
  65. data/lib/rr/times_called_matchers/at_least_matcher.rb +15 -0
  66. data/lib/rr/times_called_matchers/at_most_matcher.rb +23 -0
  67. data/lib/rr/times_called_matchers/integer_matcher.rb +19 -0
  68. data/lib/rr/times_called_matchers/never_matcher.rb +23 -0
  69. data/lib/rr/times_called_matchers/non_terminal.rb +27 -0
  70. data/lib/rr/times_called_matchers/proc_matcher.rb +11 -0
  71. data/lib/rr/times_called_matchers/range_matcher.rb +21 -0
  72. data/lib/rr/times_called_matchers/terminal.rb +20 -0
  73. data/lib/rr/times_called_matchers/times_called_matcher.rb +44 -0
  74. data/lib/rr/wildcard_matchers.rb +158 -0
  75. data/lib/rr/wildcard_matchers/anything.rb +18 -0
  76. data/lib/rr/wildcard_matchers/boolean.rb +23 -0
  77. data/lib/rr/wildcard_matchers/duck_type.rb +32 -0
  78. data/lib/rr/wildcard_matchers/hash_including.rb +29 -0
  79. data/lib/rr/wildcard_matchers/is_a.rb +25 -0
  80. data/lib/rr/wildcard_matchers/numeric.rb +13 -0
  81. data/lib/rr/wildcard_matchers/range.rb +7 -0
  82. data/lib/rr/wildcard_matchers/regexp.rb +7 -0
  83. data/lib/rr/wildcard_matchers/satisfy.rb +26 -0
  84. data/spec/api/any_instance_of/all_instances_of_spec.rb +12 -0
  85. data/spec/api/any_instance_of/any_instance_of_spec.rb +47 -0
  86. data/spec/api/any_instance_of/instance_of_spec.rb +12 -0
  87. data/spec/api/dont_allow/dont_allow_after_stub_spec.rb +14 -0
  88. data/spec/api/mock/mock_spec.rb +193 -0
  89. data/spec/api/proxy/proxy_spec.rb +86 -0
  90. data/spec/api/spy/spy_spec.rb +49 -0
  91. data/spec/api/strong/strong_spec.rb +87 -0
  92. data/spec/api/stub/stub_spec.rb +152 -0
  93. data/spec/core_spec_suite.rb +18 -0
  94. data/spec/environment_fixture_setup.rb +7 -0
  95. data/spec/minitest_spec_suite.rb +21 -0
  96. data/spec/proc_from_block_spec.rb +14 -0
  97. data/spec/rr/adapters/rr_methods_argument_matcher_spec.rb +67 -0
  98. data/spec/rr/adapters/rr_methods_creator_spec.rb +137 -0
  99. data/spec/rr/adapters/rr_methods_space_spec.rb +98 -0
  100. data/spec/rr/adapters/rr_methods_spec_helper.rb +7 -0
  101. data/spec/rr/adapters/rr_methods_times_matcher_spec.rb +13 -0
  102. data/spec/rr/double_definitions/child_double_definition_creator_spec.rb +112 -0
  103. data/spec/rr/double_definitions/double_definition_create_blank_slate_spec.rb +91 -0
  104. data/spec/rr/double_definitions/double_definition_create_spec.rb +443 -0
  105. data/spec/rr/double_injection/double_injection_spec.rb +546 -0
  106. data/spec/rr/double_injection/double_injection_verify_spec.rb +29 -0
  107. data/spec/rr/errors/rr_error_spec.rb +67 -0
  108. data/spec/rr/expectations/any_argument_expectation_spec.rb +47 -0
  109. data/spec/rr/expectations/anything_argument_equality_expectation_spec.rb +14 -0
  110. data/spec/rr/expectations/argument_equality_expectation_spec.rb +135 -0
  111. data/spec/rr/expectations/boolean_argument_equality_expectation_spec.rb +34 -0
  112. data/spec/rr/expectations/hash_including_argument_equality_expectation_spec.rb +82 -0
  113. data/spec/rr/expectations/hash_including_spec.rb +17 -0
  114. data/spec/rr/expectations/satisfy_argument_equality_expectation_spec.rb +59 -0
  115. data/spec/rr/expectations/satisfy_spec.rb +14 -0
  116. data/spec/rr/expectations/times_called_expectation/times_called_expectation_any_times_spec.rb +22 -0
  117. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_least_spec.rb +37 -0
  118. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_most_spec.rb +43 -0
  119. data/spec/rr/expectations/times_called_expectation/times_called_expectation_helper.rb +11 -0
  120. data/spec/rr/expectations/times_called_expectation/times_called_expectation_integer_spec.rb +58 -0
  121. data/spec/rr/expectations/times_called_expectation/times_called_expectation_proc_spec.rb +35 -0
  122. data/spec/rr/expectations/times_called_expectation/times_called_expectation_range_spec.rb +39 -0
  123. data/spec/rr/minitest/minitest_integration_test.rb +59 -0
  124. data/spec/rr/minitest/test_helper.rb +7 -0
  125. data/spec/rr/rspec/invocation_matcher_spec.rb +279 -0
  126. data/spec/rr/rspec/rspec_adapter_spec.rb +63 -0
  127. data/spec/rr/rspec/rspec_backtrace_tweaking_spec.rb +21 -0
  128. data/spec/rr/rspec/rspec_backtrace_tweaking_spec_fixture.rb +11 -0
  129. data/spec/rr/rspec/rspec_usage_spec.rb +86 -0
  130. data/spec/rr/space/hash_with_object_id_key_spec.rb +88 -0
  131. data/spec/rr/space/space_spec.rb +596 -0
  132. data/spec/rr/test_unit/test_helper.rb +7 -0
  133. data/spec/rr/test_unit/test_unit_backtrace_test.rb +36 -0
  134. data/spec/rr/test_unit/test_unit_integration_test.rb +59 -0
  135. data/spec/rr/times_called_matchers/any_times_matcher_spec.rb +47 -0
  136. data/spec/rr/times_called_matchers/at_least_matcher_spec.rb +55 -0
  137. data/spec/rr/times_called_matchers/at_most_matcher_spec.rb +70 -0
  138. data/spec/rr/times_called_matchers/integer_matcher_spec.rb +70 -0
  139. data/spec/rr/times_called_matchers/proc_matcher_spec.rb +55 -0
  140. data/spec/rr/times_called_matchers/range_matcher_spec.rb +76 -0
  141. data/spec/rr/times_called_matchers/times_called_matcher_spec.rb +118 -0
  142. data/spec/rr/wildcard_matchers/anything_spec.rb +24 -0
  143. data/spec/rr/wildcard_matchers/boolean_spec.rb +36 -0
  144. data/spec/rr/wildcard_matchers/duck_type_spec.rb +52 -0
  145. data/spec/rr/wildcard_matchers/is_a_spec.rb +32 -0
  146. data/spec/rr/wildcard_matchers/numeric_spec.rb +32 -0
  147. data/spec/rr/wildcard_matchers/range_spec.rb +35 -0
  148. data/spec/rr/wildcard_matchers/regexp_spec.rb +43 -0
  149. data/spec/rr_spec.rb +28 -0
  150. data/spec/rspec_spec_suite.rb +16 -0
  151. data/spec/spec_helper.rb +40 -0
  152. data/spec/spec_suite.rb +50 -0
  153. data/spec/spy_verification_spec.rb +129 -0
  154. data/spec/test_unit_spec_suite.rb +20 -0
  155. metadata +220 -0
@@ -0,0 +1,63 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
+
3
+ module RR
4
+ module Adapters
5
+ describe Rspec do
6
+ attr_reader :fixture, :subject, :method_name
7
+ describe "#setup_mocks_for_rspec" do
8
+ before do
9
+ @fixture = Object.new
10
+ fixture.extend Rspec
11
+
12
+ @subject = Object.new
13
+ @method_name = :foobar
14
+ end
15
+
16
+ it "resets the double_injections" do
17
+ stub(subject).foobar
18
+ ::RR::Injections::DoubleInjection.instances.should_not be_empty
19
+
20
+ fixture.setup_mocks_for_rspec
21
+ ::RR::Injections::DoubleInjection.instances.should be_empty
22
+ end
23
+ end
24
+
25
+ describe "#verify_mocks_for_rspec" do
26
+ before do
27
+ @fixture = Object.new
28
+ fixture.extend Rspec
29
+
30
+ @subject = Object.new
31
+ @method_name = :foobar
32
+ end
33
+
34
+ it "verifies the double_injections" do
35
+ mock(subject).foobar
36
+
37
+ lambda do
38
+ fixture.verify_mocks_for_rspec
39
+ end.should raise_error(::RR::Errors::TimesCalledError)
40
+ ::RR::Injections::DoubleInjection.instances.should be_empty
41
+ end
42
+ end
43
+
44
+ describe "#teardown_mocks_for_rspec" do
45
+ before do
46
+ @fixture = Object.new
47
+ fixture.extend Rspec
48
+
49
+ @subject = Object.new
50
+ @method_name = :foobar
51
+ end
52
+
53
+ it "resets the double_injections" do
54
+ stub(subject).foobar
55
+ ::RR::Injections::DoubleInjection.instances.should_not be_empty
56
+
57
+ fixture.teardown_mocks_for_rspec
58
+ ::RR::Injections::DoubleInjection.instances.should be_empty
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
+
3
+ module RR
4
+ module Adapters
5
+ describe Rspec do
6
+ describe "#trim_backtrace" do
7
+ it "does not set trim_backtrace" do
8
+ RR.trim_backtrace.should == false
9
+ end
10
+ end
11
+
12
+ describe "backtrace tweaking" do
13
+ it "hides rr library from the backtrace by default" do
14
+ dir = File.dirname(__FILE__)
15
+ output = `ruby #{dir}/rspec_backtrace_tweaking_spec_fixture.rb`
16
+ output.should_not include("lib/rr")
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require "spec"
3
+ dir = File.dirname(__FILE__)
4
+ require File.expand_path("#{dir}/../../../lib/rr")
5
+
6
+ describe "Example" do
7
+ it("hides RR framework in backtrace") do
8
+ mock(subject).foobar()
9
+ RR.verify_double(subject, :foobar)
10
+ end
11
+ end
@@ -0,0 +1,86 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
+
3
+ describe RR do
4
+ attr_reader :subject
5
+ before do
6
+ @subject = Object.new
7
+ end
8
+
9
+ describe "#mock" do
10
+ it "creates a mock DoubleInjection Double" do
11
+ mock(subject).foobar(1, 2) {:baz}
12
+ subject.foobar(1, 2).should == :baz
13
+ end
14
+ end
15
+
16
+ describe "#stub" do
17
+ it "creates a stub DoubleInjection Double" do
18
+ stub(subject).foobar {:baz}
19
+ subject.foobar("any", "thing").should == :baz
20
+ end
21
+ end
22
+
23
+ describe "#mock and #proxy" do
24
+ before do
25
+ def subject.foobar
26
+ :baz
27
+ end
28
+ end
29
+
30
+ it "creates a proxy DoubleInjection Double" do
31
+ mock.proxy(subject).foobar
32
+ subject.foobar.should == :baz
33
+ end
34
+ end
35
+
36
+ describe "#stub and #proxy" do
37
+ before do
38
+ def subject.foobar
39
+ :baz
40
+ end
41
+ end
42
+
43
+ it "creates a proxy DoubleInjection Double" do
44
+ stub.proxy(subject).foobar
45
+ subject.foobar.should == :baz
46
+ end
47
+ end
48
+
49
+ describe "#stub and #proxy" do
50
+ before do
51
+ def subject.foobar
52
+ :baz
53
+ end
54
+ end
55
+
56
+ it "creates a proxy DoubleInjection Double" do
57
+ stub.proxy(subject).foobar
58
+ subject.foobar.should == :baz
59
+ end
60
+ end
61
+
62
+ describe "spies" do
63
+ it "validates that a Double was called after it was called" do
64
+ stub(subject).foobar
65
+ subject.foobar(1, 2)
66
+
67
+ subject.should have_received.foobar(1, 2)
68
+ lambda do
69
+ subject.should have_received.foobar(1, 2, 3)
70
+ end.should raise_error(Spec::Expectations::ExpectationNotMetError)
71
+ end
72
+ end
73
+
74
+ it "creates an invocation matcher with a method name" do
75
+ method = :test
76
+ matcher = 'fake'
77
+ mock(RR::Adapters::Rspec::InvocationMatcher).new(method) { matcher }
78
+ have_received(method).should == matcher
79
+ end
80
+
81
+ it "creates an invocation matcher without a method name" do
82
+ matcher = 'fake'
83
+ mock(RR::Adapters::Rspec::InvocationMatcher).new(nil) { matcher }
84
+ have_received.should == matcher
85
+ end
86
+ end
@@ -0,0 +1,88 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
+
3
+ module RR
4
+ describe HashWithObjectIdKey do
5
+ describe "#[] and #[]=" do
6
+ it "stores object via object id" do
7
+ hash = HashWithObjectIdKey.new
8
+ array_1 = []
9
+ hash[array_1] = 1
10
+ array_2 = []
11
+ hash[array_2] = 2
12
+
13
+ hash[array_1].should_not == hash[array_2]
14
+ end
15
+
16
+ it "stores the passed in object" do
17
+ hash = HashWithObjectIdKey.new
18
+ obj = Object.new
19
+ hash[obj] = 1
20
+ hash.instance_eval {@keys}.should == {obj.__id__ => obj}
21
+ end
22
+ end
23
+
24
+ describe "#each" do
25
+ it "iterates through the items in the hash" do
26
+ hash = HashWithObjectIdKey.new
27
+ hash['one'] = 1
28
+ hash['two'] = 2
29
+
30
+ keys = []
31
+ values = []
32
+ hash.each do |key, value|
33
+ keys << key
34
+ values << value
35
+ end
36
+
37
+ keys.sort.should == ['one', 'two']
38
+ values.sort.should == [1, 2]
39
+ end
40
+ end
41
+
42
+ describe "#delete" do
43
+ before do
44
+ @hash = HashWithObjectIdKey.new
45
+ @key = Object.new
46
+ @hash[@key] = 1
47
+ end
48
+
49
+ it "removes the object from the hash" do
50
+ @hash.delete(@key)
51
+ @hash[@key].should be_nil
52
+ end
53
+
54
+ it "removes the object from the keys hash" do
55
+ @hash.delete(@key)
56
+ @hash.instance_eval {@keys}.should == {}
57
+ end
58
+ end
59
+
60
+ describe "#keys" do
61
+ before do
62
+ @hash = HashWithObjectIdKey.new
63
+ @key = Object.new
64
+ @hash[@key] = 1
65
+ end
66
+
67
+ it "returns an array of the keys" do
68
+ @hash.keys.should == [@key]
69
+ end
70
+ end
71
+
72
+ describe "#include?" do
73
+ before do
74
+ @hash = HashWithObjectIdKey.new
75
+ @key = Object.new
76
+ @hash[@key] = 1
77
+ end
78
+
79
+ it "returns true when the key is in the Hash" do
80
+ @hash.include?(@key).should be_true
81
+ end
82
+
83
+ it "returns false when the key is not in the Hash" do
84
+ @hash.include?(Object.new).should be_false
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,596 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
+
3
+ module RR
4
+ describe Space do
5
+ it_should_behave_like "Swapped Space"
6
+ attr_reader :subject, :method_name, :double_injection
7
+
8
+ before do
9
+ @subject = Object.new
10
+ end
11
+
12
+ describe "#record_call" do
13
+ it "should add a call to the list" do
14
+ object = Object.new
15
+ block = lambda {}
16
+ space.record_call(object, :to_s, [], block)
17
+ space.recorded_calls.should == RR::RecordedCalls.new([[object, :to_s, [], block]])
18
+ end
19
+ end
20
+
21
+ describe "#double_injection" do
22
+ context "when existing subject == but not === with the same method name" do
23
+ it "creates a new DoubleInjection" do
24
+ subject_1 = []
25
+ subject_2 = []
26
+ (subject_1 === subject_2).should be_true
27
+ subject_1.__id__.should_not == subject_2.__id__
28
+
29
+ injection_1 = Injections::DoubleInjection.find_or_create_by_subject(subject_1, :foobar)
30
+ injection_2 = Injections::DoubleInjection.find_or_create_by_subject(subject_2, :foobar)
31
+
32
+ injection_1.should_not == injection_2
33
+ end
34
+ end
35
+
36
+ context "when a DoubleInjection is not registered for the subject and method_name" do
37
+ before do
38
+ def subject.foobar(*args)
39
+ :original_foobar
40
+ end
41
+
42
+ @method_name = :foobar
43
+ end
44
+
45
+ context "when method_name is a symbol" do
46
+ it "returns double_injection and adds double_injection to double_injection list" do
47
+ double_injection = Injections::DoubleInjection.find_or_create_by_subject(subject, method_name)
48
+ Injections::DoubleInjection.find_or_create_by_subject(subject, method_name).should === double_injection
49
+ double_injection.subject_class.should == (class << subject; self; end)
50
+ double_injection.method_name.should === method_name
51
+ end
52
+ end
53
+
54
+ context "when method_name is a string" do
55
+ it "returns double_injection and adds double_injection to double_injection list" do
56
+ double_injection = Injections::DoubleInjection.find_or_create_by_subject(subject, 'foobar')
57
+ Injections::DoubleInjection.find_or_create_by_subject(subject, method_name).should === double_injection
58
+ double_injection.subject_class.should == (class << subject; self; end)
59
+ double_injection.method_name.should === method_name
60
+ end
61
+ end
62
+
63
+ it "overrides the method when passing a block" do
64
+ original_method = subject.method(:foobar)
65
+ Injections::DoubleInjection.find_or_create_by_subject(subject, method_name)
66
+ subject.method(:foobar).should_not == original_method
67
+ end
68
+ end
69
+
70
+ context "when double_injection exists" do
71
+ before do
72
+ def subject.foobar(*args)
73
+ :original_foobar
74
+ end
75
+
76
+ @method_name = :foobar
77
+ end
78
+
79
+ context "when a DoubleInjection is registered for the subject and method_name" do
80
+ it "returns the existing DoubleInjection" do
81
+ @double_injection = Injections::DoubleInjection.find_or_create_by_subject(subject, 'foobar')
82
+
83
+ double_injection.subject_has_original_method?.should be_true
84
+
85
+ Injections::DoubleInjection.find_or_create_by_subject(subject, 'foobar').should === double_injection
86
+
87
+ double_injection.reset
88
+ subject.foobar.should == :original_foobar
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ describe "#method_missing_injection" do
95
+ context "when existing subject == but not === with the same method name" do
96
+ it "creates a new DoubleInjection" do
97
+ subject_1 = []
98
+ subject_2 = []
99
+ (subject_1 === subject_2).should be_true
100
+ subject_1.__id__.should_not == subject_2.__id__
101
+
102
+ injection_1 = Injections::MethodMissingInjection.find_or_create(class << subject_1; self; end)
103
+ injection_2 = Injections::MethodMissingInjection.find_or_create(class << subject_2; self; end)
104
+
105
+ injection_1.should_not == injection_2
106
+ end
107
+ end
108
+
109
+ context "when a MethodMissingInjection is not registered for the subject and method_name" do
110
+ before do
111
+ def subject.method_missing(method_name, *args, &block)
112
+ :original_method_missing
113
+ end
114
+ end
115
+
116
+ it "overrides the method when passing a block" do
117
+ original_method = subject.method(:method_missing)
118
+ Injections::MethodMissingInjection.find_or_create(class << subject; self; end)
119
+ subject.method(:method_missing).should_not == original_method
120
+ end
121
+ end
122
+
123
+ context "when a MethodMissingInjection is registered for the subject and method_name" do
124
+ before do
125
+ def subject.method_missing(method_name, *args, &block)
126
+ :original_method_missing
127
+ end
128
+ end
129
+
130
+ context "when a DoubleInjection is registered for the subject and method_name" do
131
+ it "returns the existing DoubleInjection" do
132
+ injection = Injections::MethodMissingInjection.find_or_create(class << subject; self; end)
133
+ injection.subject_has_original_method?.should be_true
134
+
135
+ Injections::MethodMissingInjection.find_or_create(class << subject; self; end).should === injection
136
+
137
+ injection.reset
138
+ subject.method_missing(:foobar).should == :original_method_missing
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ describe "#singleton_method_added_injection" do
145
+ context "when existing subject == but not === with the same method name" do
146
+ it "creates a new DoubleInjection" do
147
+ subject_1 = []
148
+ subject_2 = []
149
+ (subject_1 === subject_2).should be_true
150
+ subject_1.__id__.should_not == subject_2.__id__
151
+
152
+ injection_1 = Injections::SingletonMethodAddedInjection.find_or_create(class << subject_1; self; end)
153
+ injection_2 = Injections::SingletonMethodAddedInjection.find_or_create(class << subject_2; self; end)
154
+
155
+ injection_1.should_not == injection_2
156
+ end
157
+ end
158
+
159
+ context "when a SingletonMethodAddedInjection is not registered for the subject and method_name" do
160
+ before do
161
+ def subject.singleton_method_added(method_name)
162
+ :original_singleton_method_added
163
+ end
164
+ end
165
+
166
+ it "overrides the method when passing a block" do
167
+ original_method = subject.method(:singleton_method_added)
168
+ Injections::SingletonMethodAddedInjection.find_or_create(class << subject; self; end)
169
+ subject.method(:singleton_method_added).should_not == original_method
170
+ end
171
+ end
172
+
173
+ context "when a SingletonMethodAddedInjection is registered for the subject and method_name" do
174
+ before do
175
+ def subject.singleton_method_added(method_name)
176
+ :original_singleton_method_added
177
+ end
178
+ end
179
+
180
+ context "when a DoubleInjection is registered for the subject and method_name" do
181
+ it "returns the existing DoubleInjection" do
182
+ injection = Injections::SingletonMethodAddedInjection.find_or_create(class << subject; self; end)
183
+ injection.subject_has_original_method?.should be_true
184
+
185
+ Injections::SingletonMethodAddedInjection.find_or_create(class << subject; self; end).should === injection
186
+
187
+ injection.reset
188
+ subject.singleton_method_added(:foobar).should == :original_singleton_method_added
189
+ end
190
+ end
191
+ end
192
+ end
193
+
194
+ describe "#reset" do
195
+ attr_reader :subject_1, :subject_2
196
+ before do
197
+ @subject_1 = Object.new
198
+ @subject_2 = Object.new
199
+ @method_name = :foobar
200
+ end
201
+
202
+ it "should clear the #recorded_calls" do
203
+ object = Object.new
204
+ space.record_call(object, :to_s, [], nil)
205
+
206
+ space.reset
207
+ space.recorded_calls.should == RR::RecordedCalls.new([])
208
+ end
209
+
210
+ it "removes the ordered doubles" do
211
+ mock(subject_1).foobar1.ordered
212
+ mock(subject_2).foobar2.ordered
213
+
214
+ space.ordered_doubles.should_not be_empty
215
+
216
+ space.reset
217
+ space.ordered_doubles.should be_empty
218
+ end
219
+
220
+ it "resets all double_injections" do
221
+ subject_1.respond_to?(method_name).should be_false
222
+ subject_2.respond_to?(method_name).should be_false
223
+
224
+ Injections::DoubleInjection.find_or_create_by_subject(subject_1, method_name)
225
+ Injections::DoubleInjection.exists_by_subject?(subject_1, method_name).should be_true
226
+ subject_1.respond_to?(method_name).should be_true
227
+
228
+ Injections::DoubleInjection.find_or_create_by_subject(subject_2, method_name)
229
+ Injections::DoubleInjection.exists_by_subject?(subject_2, method_name).should be_true
230
+ subject_2.respond_to?(method_name).should be_true
231
+
232
+ space.reset
233
+
234
+ subject_1.respond_to?(method_name).should be_false
235
+ Injections::DoubleInjection.exists?(subject_1, method_name).should be_false
236
+
237
+ subject_2.respond_to?(method_name).should be_false
238
+ Injections::DoubleInjection.exists?(subject_2, method_name).should be_false
239
+ end
240
+
241
+ it "resets all method_missing_injections" do
242
+ subject_1.respond_to?(:method_missing).should be_false
243
+ subject_2.respond_to?(:method_missing).should be_false
244
+
245
+ Injections::MethodMissingInjection.find_or_create(class << subject_1; self; end)
246
+ Injections::MethodMissingInjection.exists?(class << subject_1; self; end).should be_true
247
+ subject_1.respond_to?(:method_missing).should be_true
248
+
249
+ Injections::MethodMissingInjection.find_or_create(class << subject_2; self; end)
250
+ Injections::MethodMissingInjection.exists?(class << subject_2; self; end).should be_true
251
+ subject_2.respond_to?(:method_missing).should be_true
252
+
253
+ space.reset
254
+
255
+ subject_1.respond_to?(:method_missing).should be_false
256
+ Injections::MethodMissingInjection.exists?(subject_1).should be_false
257
+
258
+ subject_2.respond_to?(:method_missing).should be_false
259
+ Injections::MethodMissingInjection.exists?(subject_2).should be_false
260
+ end
261
+
262
+ it "resets all singleton_method_added_injections" do
263
+ subject_1.respond_to?(:singleton_method_added).should be_false
264
+ subject_2.respond_to?(:singleton_method_added).should be_false
265
+
266
+ Injections::SingletonMethodAddedInjection.find_or_create(class << subject_1; self; end)
267
+ Injections::SingletonMethodAddedInjection.exists?(class << subject_1; self; end).should be_true
268
+ subject_1.respond_to?(:singleton_method_added).should be_true
269
+
270
+ Injections::SingletonMethodAddedInjection.find_or_create(class << subject_2; self; end)
271
+ Injections::SingletonMethodAddedInjection.exists?(class << subject_2; self; end).should be_true
272
+ subject_2.respond_to?(:singleton_method_added).should be_true
273
+
274
+ space.reset
275
+
276
+ subject_1.respond_to?(:singleton_method_added).should be_false
277
+ Injections::SingletonMethodAddedInjection.exists?(subject_1).should be_false
278
+
279
+ subject_2.respond_to?(:singleton_method_added).should be_false
280
+ Injections::SingletonMethodAddedInjection.exists?(subject_2).should be_false
281
+ end
282
+
283
+ it "clears RR::Injections::DoubleInjection::BoundObjects" do
284
+ stub(subject).foobar
285
+ RR::Injections::DoubleInjection::BoundObjects.should_not be_empty
286
+ space.reset
287
+ pending "Clearing BoundObjects" do
288
+ RR::Injections::DoubleInjection::BoundObjects.should be_empty
289
+ end
290
+ end
291
+ end
292
+
293
+ describe "#reset_double" do
294
+ before do
295
+ @method_name = :foobar
296
+
297
+ def subject.foobar
298
+ end
299
+ end
300
+
301
+ it "resets the double_injections and restores the original method" do
302
+ original_method = subject.method(method_name)
303
+
304
+ @double_injection = Injections::DoubleInjection.find_or_create_by_subject(subject, method_name)
305
+ Injections::DoubleInjection.instances.keys.should include(class << subject; self; end)
306
+ Injections::DoubleInjection.find_by_subject(subject, method_name).should_not be_nil
307
+ subject.method(method_name).should_not == original_method
308
+
309
+ space.reset_double(subject, method_name)
310
+ Injections::DoubleInjection.instances.keys.should_not include(subject)
311
+ subject.method(method_name).should == original_method
312
+ end
313
+
314
+ context "when it has no double_injections" do
315
+ it "removes the subject from the double_injections map" do
316
+ double_1 = Injections::DoubleInjection.find_or_create_by_subject(subject, :foobar1)
317
+ double_2 = Injections::DoubleInjection.find_or_create_by_subject(subject, :foobar2)
318
+
319
+ Injections::DoubleInjection.instances.include?(class << subject; self; end).should == true
320
+ Injections::DoubleInjection.find_by_subject(subject, :foobar1).should_not be_nil
321
+ Injections::DoubleInjection.find_by_subject(subject, :foobar2).should_not be_nil
322
+
323
+ space.reset_double(subject, :foobar1)
324
+ Injections::DoubleInjection.instances.include?(class << subject; self; end).should == true
325
+ Injections::DoubleInjection.find_by_subject(subject, :foobar1).should be_nil
326
+ Injections::DoubleInjection.find_by_subject(subject, :foobar2).should_not be_nil
327
+
328
+ space.reset_double(subject, :foobar2)
329
+ Injections::DoubleInjection.instances.include?(subject).should == false
330
+ end
331
+ end
332
+ end
333
+
334
+ describe "#DoubleInjection.reset" do
335
+ attr_reader :subject_1, :subject_2
336
+ before do
337
+ @subject_1 = Object.new
338
+ @subject_2 = Object.new
339
+ @method_name = :foobar
340
+ end
341
+
342
+ it "resets the double_injection and removes it from the double_injections list" do
343
+ double_injection_1 = Injections::DoubleInjection.find_or_create_by_subject(subject_1, method_name)
344
+ double_1_reset_call_count = 0
345
+ ( class << double_injection_1; self; end).class_eval do
346
+ define_method(:reset) do
347
+ double_1_reset_call_count += 1
348
+ end
349
+ end
350
+ double_injection_2 = Injections::DoubleInjection.find_or_create_by_subject(subject_2, method_name)
351
+ double_2_reset_call_count = 0
352
+ ( class << double_injection_2; self; end).class_eval do
353
+ define_method(:reset) do
354
+ double_2_reset_call_count += 1
355
+ end
356
+ end
357
+
358
+ Injections::DoubleInjection.reset
359
+ double_1_reset_call_count.should == 1
360
+ double_2_reset_call_count.should == 1
361
+ end
362
+ end
363
+
364
+ describe "#verify_doubles" do
365
+ attr_reader :subject_1, :subject_2, :subject3, :double_1, :double_2, :double3
366
+ before do
367
+ @subject_1 = Object.new
368
+ @subject_2 = Object.new
369
+ @subject3 = Object.new
370
+ @method_name = :foobar
371
+ @double_1 = Injections::DoubleInjection.find_or_create_by_subject(subject_1, method_name)
372
+ @double_2 = Injections::DoubleInjection.find_or_create_by_subject(subject_2, method_name)
373
+ @double3 = Injections::DoubleInjection.find_or_create_by_subject(subject3, method_name)
374
+ end
375
+
376
+ context "when passed no arguments" do
377
+ it "verifies and deletes the double_injections" do
378
+ double_1_verify_call_count = 0
379
+ double_1_reset_call_count = 0
380
+ (
381
+ class << double_1;
382
+ self;
383
+ end).class_eval do
384
+ define_method(:verify) do
385
+ double_1_verify_call_count += 1
386
+ end
387
+ define_method(:reset) do
388
+ double_1_reset_call_count += 1
389
+ end
390
+ end
391
+
392
+ double_2_verify_call_count = 0
393
+ double_2_reset_call_count = 0
394
+ (
395
+ class << double_2;
396
+ self;
397
+ end).class_eval do
398
+ define_method(:verify) do
399
+ double_2_verify_call_count += 1
400
+ end
401
+ define_method(:reset) do
402
+ double_2_reset_call_count += 1
403
+ end
404
+ end
405
+
406
+ space.verify_doubles
407
+ double_1_verify_call_count.should == 1
408
+ double_2_verify_call_count.should == 1
409
+ double_1_reset_call_count.should == 1
410
+ double_1_reset_call_count.should == 1
411
+ end
412
+ end
413
+
414
+ context "when passed an Object that has at least one DoubleInjection" do
415
+ it "verifies all Doubles injected into the Object" do
416
+ double_1_verify_call_count = 0
417
+ double_1_reset_call_count = 0
418
+ (
419
+ class << double_1;
420
+ self;
421
+ end).class_eval do
422
+ define_method(:verify) do
423
+ double_1_verify_call_count += 1
424
+ end
425
+ define_method(:reset) do
426
+ double_1_reset_call_count += 1
427
+ end
428
+ end
429
+
430
+ double_2_verify_call_count = 0
431
+ double_2_reset_call_count = 0
432
+ (
433
+ class << double_2;
434
+ self;
435
+ end).class_eval do
436
+ define_method(:verify) do
437
+ double_2_verify_call_count += 1
438
+ end
439
+ define_method(:reset) do
440
+ double_2_reset_call_count += 1
441
+ end
442
+ end
443
+
444
+ space.verify_doubles(subject_1)
445
+
446
+ double_1_verify_call_count.should == 1
447
+ double_1_reset_call_count.should == 1
448
+ double_2_verify_call_count.should == 0
449
+ double_2_reset_call_count.should == 0
450
+ end
451
+ end
452
+
453
+ context "when passed multiple Objects with at least one DoubleInjection" do
454
+ it "verifies the Doubles injected into all of the Objects" do
455
+ double_1_verify_call_count = 0
456
+ double_1_reset_call_count = 0
457
+ ( class << double_1; self; end).class_eval do
458
+ define_method(:verify) do
459
+ double_1_verify_call_count += 1
460
+ end
461
+ define_method(:reset) do
462
+ double_1_reset_call_count += 1
463
+ end
464
+ end
465
+
466
+ double_2_verify_call_count = 0
467
+ double_2_reset_call_count = 0
468
+ ( class << double_2; self; end).class_eval do
469
+ define_method(:verify) do
470
+ double_2_verify_call_count += 1
471
+ end
472
+ define_method(:reset) do
473
+ double_2_reset_call_count += 1
474
+ end
475
+ end
476
+
477
+ double3_verify_call_count = 0
478
+ double3_reset_call_count = 0
479
+ ( class << double3; self; end).class_eval do
480
+ define_method(:verify) do
481
+ double3_verify_call_count += 1
482
+ end
483
+ define_method(:reset) do
484
+ double3_reset_call_count += 1
485
+ end
486
+ end
487
+
488
+ space.verify_doubles(subject_1, subject_2)
489
+
490
+ double_1_verify_call_count.should == 1
491
+ double_1_reset_call_count.should == 1
492
+ double_2_verify_call_count.should == 1
493
+ double_2_reset_call_count.should == 1
494
+ double3_verify_call_count.should == 0
495
+ double3_reset_call_count.should == 0
496
+ end
497
+ end
498
+
499
+ context "when passed an subject that does not have a DoubleInjection" do
500
+ it "does not raise an error" do
501
+ double_1_verify_call_count = 0
502
+ double_1_reset_call_count = 0
503
+ ( class << double_1; self; end).class_eval do
504
+ define_method(:verify) do
505
+ double_1_verify_call_count += 1
506
+ end
507
+ define_method(:reset) do
508
+ double_1_reset_call_count += 1
509
+ end
510
+ end
511
+
512
+ double_2_verify_call_count = 0
513
+ double_2_reset_call_count = 0
514
+ ( class << double_2; self; end).class_eval do
515
+ define_method(:verify) do
516
+ double_2_verify_call_count += 1
517
+ end
518
+ define_method(:reset) do
519
+ double_2_reset_call_count += 1
520
+ end
521
+ end
522
+
523
+ double3_verify_call_count = 0
524
+ double3_reset_call_count = 0
525
+ ( class << double3; self; end).class_eval do
526
+ define_method(:verify) do
527
+ double3_verify_call_count += 1
528
+ end
529
+ define_method(:reset) do
530
+ double3_reset_call_count += 1
531
+ end
532
+ end
533
+
534
+ no_double_injection_object = Object.new
535
+ space.verify_doubles(no_double_injection_object)
536
+
537
+ double_1_verify_call_count.should == 0
538
+ double_1_reset_call_count.should == 0
539
+ double_2_verify_call_count.should == 0
540
+ double_2_reset_call_count.should == 0
541
+ double3_verify_call_count.should == 0
542
+ double3_reset_call_count.should == 0
543
+ end
544
+ end
545
+ end
546
+
547
+ describe "#verify_double" do
548
+ before do
549
+ @method_name = :foobar
550
+
551
+ def subject.foobar
552
+ end
553
+ end
554
+
555
+ it "verifies and deletes the double_injection" do
556
+ @double_injection = Injections::DoubleInjection.find_or_create_by_subject(subject, method_name)
557
+ Injections::DoubleInjection.find_by_subject(subject, method_name).should === double_injection
558
+
559
+ verify_call_count = 0
560
+ ( class << double_injection; self; end).class_eval do
561
+ define_method(:verify) do
562
+ verify_call_count += 1
563
+ end
564
+ end
565
+ space.verify_double(subject, method_name)
566
+ verify_call_count.should == 1
567
+
568
+ Injections::DoubleInjection.find(subject, method_name).should be_nil
569
+ end
570
+
571
+ context "when verifying the double_injection raises an error" do
572
+ it "deletes the double_injection and restores the original method" do
573
+ original_method = subject.method(method_name)
574
+
575
+ @double_injection = Injections::DoubleInjection.find_or_create_by_subject(subject, method_name)
576
+ subject.method(method_name).should_not == original_method
577
+
578
+ Injections::DoubleInjection.find_by_subject(subject, method_name).should === double_injection
579
+
580
+ verify_called = true
581
+ ( class << double_injection; self; end).class_eval do
582
+ define_method(:verify) do
583
+ verify_called = true
584
+ raise "An Error"
585
+ end
586
+ end
587
+ lambda {space.verify_double(subject, method_name)}.should raise_error
588
+ verify_called.should be_true
589
+
590
+ Injections::DoubleInjection.find(subject, method_name).should be_nil
591
+ subject.method(method_name).should == original_method
592
+ end
593
+ end
594
+ end
595
+ end
596
+ end