rr 0.10.2 → 0.10.4

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.
data/spec/spec_helper.rb CHANGED
@@ -3,6 +3,7 @@ require "#{dir}/environment_fixture_setup"
3
3
  require "#{dir}/rr/expectations/times_called_expectation/times_called_expectation_helper"
4
4
  require "#{dir}/rr/adapters/rr_methods_spec_helper"
5
5
  ARGV.push("--format", "nested") unless ARGV.include?("--format")
6
+ ARGV.push("-b")
6
7
 
7
8
  Spec::Runner.configure do |config|
8
9
  config.mock_with RR::Adapters::Rspec
@@ -105,4 +106,8 @@ class Spec::ExampleGroup
105
106
  double_definition
106
107
  )
107
108
  end
109
+
110
+ def eigen(object)
111
+ class << object; self; end
112
+ end
108
113
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.2
4
+ version: 0.10.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Takita
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-30 00:00:00 -07:00
12
+ date: 2009-09-26 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -48,7 +48,6 @@ files:
48
48
  - lib/rr/double_definitions/strategies/verification/mock.rb
49
49
  - lib/rr/double_definitions/strategies/verification/stub.rb
50
50
  - lib/rr/double_definitions/strategies/verification/verification_strategy.rb
51
- - lib/rr/double_injection.rb
52
51
  - lib/rr/double_matches.rb
53
52
  - lib/rr/errors/argument_equality_error.rb
54
53
  - lib/rr/errors/double_definition_error.rb
@@ -65,6 +64,13 @@ files:
65
64
  - lib/rr/expectations/argument_equality_expectation.rb
66
65
  - lib/rr/expectations/times_called_expectation.rb
67
66
  - lib/rr/hash_with_object_id_key.rb
67
+ - lib/rr/injections/double_injection.rb
68
+ - lib/rr/injections/injection.rb
69
+ - lib/rr/injections/method_missing_injection.rb
70
+ - lib/rr/injections/singleton_method_added_injection.rb
71
+ - lib/rr/method_dispatches/base_method_dispatch.rb
72
+ - lib/rr/method_dispatches/method_dispatch.rb
73
+ - lib/rr/method_dispatches/method_missing_dispatch.rb
68
74
  - lib/rr/proc_from_block.rb
69
75
  - lib/rr/recorded_calls.rb
70
76
  - lib/rr/space.rb
@@ -102,10 +108,6 @@ files:
102
108
  - spec/rr/double_definitions/double_definition_creator_proxy_spec.rb
103
109
  - spec/rr/double_definitions/double_definition_creator_spec.rb
104
110
  - spec/rr/double_definitions/double_definition_spec.rb
105
- - spec/rr/double_injection/double_injection_bind_spec.rb
106
- - spec/rr/double_injection/double_injection_dispatching_spec.rb
107
- - spec/rr/double_injection/double_injection_has_original_method_spec.rb
108
- - spec/rr/double_injection/double_injection_reset_spec.rb
109
111
  - spec/rr/double_injection/double_injection_spec.rb
110
112
  - spec/rr/double_injection/double_injection_verify_spec.rb
111
113
  - spec/rr/double_spec.rb
@@ -1,136 +0,0 @@
1
- module RR
2
- # RR::DoubleInjection is the binding of an subject and a method.
3
- # A double_injection has 0 to many Double objects. Each Double
4
- # has Argument Expectations and Times called Expectations.
5
- class DoubleInjection
6
- include Space::Reader
7
-
8
- LAZY_METHOD_DEFINITIONS = [
9
- (lambda do |subject|
10
- subject.respond_to?(:descends_from_active_record?) && subject.descends_from_active_record?
11
- end)
12
- ]
13
-
14
- MethodArguments = Struct.new(:arguments, :block)
15
- attr_reader :subject, :method_name, :doubles, :subject_class
16
-
17
- def initialize(subject, method_name, subject_class)
18
- @subject = subject
19
- @subject_class = subject_class
20
- @method_name = method_name.to_sym
21
- if subject_respond_to_method?(method_name)
22
- if LAZY_METHOD_DEFINITIONS.any? {|definition| definition.call(subject)} && !subject.methods.include?(method_name)
23
- subject.send(method_name)
24
- end
25
- subject_class.__send__(:alias_method, original_method_alias_name, method_name)
26
- end
27
- @doubles = []
28
- end
29
-
30
- # RR::DoubleInjection#register_double adds the passed in Double
31
- # into this DoubleInjection's list of Double objects.
32
- def register_double(double)
33
- @doubles << double
34
- end
35
-
36
- # RR::DoubleInjection#bind injects a method that acts as a dispatcher
37
- # that dispatches to the matching Double when the method
38
- # is called.
39
- def bind
40
- returns_method = <<-METHOD
41
- def #{@method_name}(*args, &block)
42
- arguments = MethodArguments.new(args, block)
43
- RR::Space.double_injection(self, :#{@method_name}).call_method(arguments.arguments, arguments.block)
44
- end
45
- METHOD
46
- subject_class.class_eval(returns_method, __FILE__, __LINE__ - 5)
47
- self
48
- end
49
-
50
- # RR::DoubleInjection#verify verifies each Double
51
- # TimesCalledExpectation are met.
52
- def verify
53
- @doubles.each do |double|
54
- double.verify
55
- end
56
- end
57
-
58
- # RR::DoubleInjection#reset removes the injected dispatcher method.
59
- # It binds the original method implementation on the subject
60
- # if one exists.
61
- def reset
62
- if object_has_original_method?
63
- subject_class.__send__(:alias_method, @method_name, original_method_alias_name)
64
- subject_class.__send__(:remove_method, original_method_alias_name)
65
- else
66
- subject_class.__send__(:remove_method, @method_name)
67
- end
68
- end
69
-
70
- def call_original_method(*args, &block)
71
- @subject.__send__(original_method_alias_name, *args, &block)
72
- end
73
-
74
- def object_has_original_method?
75
- subject_respond_to_method?(original_method_alias_name)
76
- end
77
-
78
- def call_method(args, block)
79
- space.record_call(subject, method_name, args, block)
80
- if double = find_double_to_attempt(args)
81
- double.call(self, *args, &block)
82
- else
83
- double_not_found_error(*args)
84
- end
85
- end
86
-
87
- protected
88
- def find_double_to_attempt(args)
89
- matches = DoubleMatches.new(@doubles).find_all_matches(args)
90
-
91
- unless matches.exact_terminal_doubles_to_attempt.empty?
92
- return matches.exact_terminal_doubles_to_attempt.first
93
- end
94
-
95
- unless matches.exact_non_terminal_doubles_to_attempt.empty?
96
- return matches.exact_non_terminal_doubles_to_attempt.last
97
- end
98
-
99
- unless matches.wildcard_terminal_doubles_to_attempt.empty?
100
- return matches.wildcard_terminal_doubles_to_attempt.first
101
- end
102
-
103
- unless matches.wildcard_non_terminal_doubles_to_attempt.empty?
104
- return matches.wildcard_non_terminal_doubles_to_attempt.last
105
- end
106
-
107
- unless matches.matching_doubles.empty?
108
- return matches.matching_doubles.first # This will raise a TimesCalledError
109
- end
110
-
111
- return nil
112
- end
113
-
114
- def double_not_found_error(*args)
115
- message =
116
- "On subject #{subject},\n" <<
117
- "unexpected method invocation:\n" <<
118
- " #{Double.formatted_name(@method_name, args)}\n" <<
119
- "expected invocations:\n" <<
120
- Double.list_message_part(@doubles)
121
- raise Errors::DoubleNotFoundError, message
122
- end
123
-
124
- def original_method_alias_name
125
- "__rr__original_#{@method_name}"
126
- end
127
-
128
- def subject_respond_to_method?(method_name)
129
- subject_has_method_defined?(method_name) || @subject.respond_to?(method_name)
130
- end
131
-
132
- def subject_has_method_defined?(method_name)
133
- @subject.methods.include?(method_name.to_s) || @subject.protected_methods.include?(method_name.to_s) || @subject.private_methods.include?(method_name.to_s)
134
- end
135
- end
136
- end
@@ -1,99 +0,0 @@
1
- require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
-
3
- module RR
4
- module DoubleDefinitions
5
- describe DoubleInjection do
6
- attr_reader :subject, :method_name, :double_injection, :original_method
7
- describe "#bind" do
8
- context "with an existing method" do
9
- before do
10
- @subject = Object.new
11
- @method_name = :foobar
12
- def subject.foobar;
13
- :original_foobar;
14
- end
15
- @original_method = @subject.method(method_name)
16
- @subject.methods.should include(method_name.to_s)
17
-
18
- subject.method(:foobar).should == original_method
19
- end
20
-
21
- context "when the existing method is public" do
22
- before do
23
- stub(subject, method_name).returns {:new_foobar}
24
- end
25
-
26
- it "returns the value of the Double Injection" do
27
- subject.foobar.should == :new_foobar
28
- end
29
-
30
- it "overrides the original method with the double_injection's dispatching methods" do
31
- subject.method(:foobar).should_not == original_method
32
- end
33
-
34
- it "stores original method in __rr__original_method_alias_name" do
35
- subject.respond_to?(:__rr__original_foobar).should == true
36
- subject.method(:__rr__original_foobar).should == original_method
37
- end
38
- end
39
-
40
- context "when the existing method is private" do
41
- before do
42
- class << subject
43
- private :foobar
44
- end
45
- @double_injection = RR::Space.double_injection(subject, method_name)
46
- end
47
-
48
- it "overrides the original method with the double_injection's dispatching methods" do
49
- double_injection.bind
50
- subject.method(:foobar).should_not == original_method
51
- end
52
-
53
- it "stores original method in __rr__original_method_alias_name" do
54
- subject.private_methods.should include('__rr__original_foobar')
55
- subject.method(:__rr__original_foobar).should == original_method
56
- end
57
- end
58
- end
59
-
60
- context "without an existing method" do
61
- before do
62
- @subject = Object.new
63
- @method_name = :foobar
64
- subject.methods.should_not include(method_name.to_s)
65
- RR::Space.double_injection(subject, method_name)
66
- end
67
-
68
- it "creates a new method with the double_injection's dispatching methods" do
69
- subject.method(method_name).should_not be_nil
70
- end
71
-
72
- it "does not create method __rr__original_method_alias_name" do
73
- subject.respond_to?(:__rr__original_foobar).should == false
74
- end
75
- end
76
-
77
- context "with #==" do
78
- before do
79
- @subject = Object.new
80
- @method_name = :'=='
81
- subject.should respond_to(method_name)
82
- @original_method = subject.method(method_name)
83
- subject.methods.should include(method_name.to_s)
84
- @double_injection = RR::Space.double_injection(subject, method_name)
85
- end
86
-
87
- it "overrides the original method with the double_injection's dispatching methods" do
88
- subject.method(method_name).should_not == original_method
89
- end
90
-
91
- it "stores original method in __rr__original_method_alias_name" do
92
- subject.respond_to?(:"__rr__original_#{method_name}").should == true
93
- subject.method(:"__rr__original_#{method_name}").should == original_method
94
- end
95
- end
96
- end
97
- end
98
- end
99
- end
@@ -1,244 +0,0 @@
1
- require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
-
3
- module RR
4
- describe DoubleInjection do
5
- attr_reader :space, :subject, :double_injection
6
- it_should_behave_like "Swapped Space"
7
- before do
8
- @subject = Object.new
9
- subject.methods.should_not include(method_name.to_s)
10
- @double_injection = space.double_injection(subject, method_name)
11
- end
12
-
13
- def new_double
14
- Double.new(
15
- double_injection,
16
- DoubleDefinitions::DoubleDefinition.new(
17
- DoubleDefinitions::DoubleDefinitionCreator.new,
18
- subject
19
- ).any_number_of_times
20
- )
21
- end
22
-
23
- describe "methods whose name do not contain ! or ?" do
24
- def method_name
25
- :foobar
26
- end
27
-
28
- context "when the original method uses the passed-in block" do
29
- it "executes the passed-in block" do
30
- method_fixture = Object.new
31
- class << method_fixture
32
- def method_with_block(a, b)
33
- yield(a, b)
34
- end
35
- end
36
- double = new_double
37
- double.definition.with(1, 2).implemented_by(method_fixture.method(:method_with_block))
38
- subject.foobar(1, 2) {|a, b| [b, a]}.should == [2, 1]
39
- end
40
- end
41
-
42
- context "when no other Double with duplicate ArgumentExpectations exists" do
43
- it "dispatches to Double that have an exact match" do
44
- double1_with_exact_match = new_double
45
- double1_with_exact_match.definition.with(:exact_match_1).returns {:return_1}
46
- double_with_no_match = new_double
47
- double_with_no_match.definition.with("nothing that matches").returns {:no_match}
48
- double2_with_exact_match = new_double
49
- double2_with_exact_match.definition.with(:exact_match_2).returns {:return_2}
50
-
51
- subject.foobar(:exact_match_1).should == :return_1
52
- subject.foobar(:exact_match_2).should == :return_2
53
- end
54
-
55
- it "dispatches to Double that have a wildcard match" do
56
- double_with_wildcard_match = new_double
57
- double_with_wildcard_match.definition.with_any_args.returns {:wild_card_value}
58
- double_with_no_match = new_double
59
- double_with_no_match.definition.with("nothing that matches").returns {:no_match}
60
-
61
- subject.foobar(:wildcard_match_1).should == :wild_card_value
62
- subject.foobar(:wildcard_match_2, 3).should == :wild_card_value
63
- end
64
- end
65
-
66
- context "when other Doubles exists but none of them match the passed-in arguments" do
67
- it "raises DoubleNotFoundError error when arguments do not match a double" do
68
- double_1 = new_double
69
- double_1.definition.with(1, 2)
70
-
71
- double_2 = new_double
72
- double_2.definition.with(3)
73
-
74
- error = nil
75
- begin
76
- subject.foobar(:arg1, :arg2)
77
- viotated "Error should have been raised"
78
- rescue Errors::DoubleNotFoundError => e
79
- error = e
80
- end
81
- error.message.should include("On subject #<Object")
82
- expected_double_message_part = "unexpected method invocation:\n" <<
83
- " foobar(:arg1, :arg2)\n"
84
- "expected invocations:\n"
85
- "- foobar(1, 2)\n" <<
86
- "- foobar(3)"
87
- error.message.should include(expected_double_message_part)
88
- end
89
- end
90
-
91
- context "when at least one Double with NonTerminal TimesCalledMatchers exits" do
92
- it "dispatches to Double with exact match" do
93
- double = new_double(1, 2) {:return_value}
94
- subject.foobar(1, 2).should == :return_value
95
- end
96
-
97
- it "matches to the last Double that was registered with an exact match" do
98
- double_1 = new_double(1, 2) {:value_1}
99
- double_2 = new_double(1, 2) {:value_2}
100
-
101
- subject.foobar(1, 2).should == :value_2
102
- end
103
-
104
- it "dispatches to Double with wildcard match" do
105
- new_double(anything) {:return_value}
106
- subject.foobar(:dont_care).should == :return_value
107
- end
108
-
109
- it "matches to the last Double that was registered with a wildcard match" do
110
- new_double(anything) {:value_1}
111
- new_double(anything) {:value_2}
112
-
113
- subject.foobar(:dont_care).should == :value_2
114
- end
115
-
116
- it "matches to Double with exact match Double even when a Double with wildcard match was registered later" do
117
- new_double(1, 2) {:exact_first}
118
- new_double(anything, anything) {:wildcard_last}
119
-
120
- subject.foobar(1, 2).should == :exact_first
121
- end
122
-
123
- def new_double(*arguments, &return_value)
124
- double = super()
125
- double.definition.with(*arguments).any_number_of_times.returns(&return_value)
126
- double.should_not be_terminal
127
- double
128
- end
129
- end
130
-
131
- context "when two or more Terminal Doubles with duplicate Exact Match ArgumentExpectations exists" do
132
- it "dispatches to Double that have an exact match" do
133
- new_double(:exact_match) {:return_1}
134
-
135
- subject.foobar(:exact_match).should == :return_1
136
- end
137
-
138
- it "dispatches to the first Double that have an exact match" do
139
- new_double(:exact_match) {:return_1}
140
- new_double(:exact_match) {:return_2}
141
-
142
- subject.foobar(:exact_match).should == :return_1
143
- end
144
-
145
- it "dispatches the second Double with an exact match
146
- when the first double's Times Called expectation is satisfied" do
147
- new_double(:exact_match) {:return_1}
148
- new_double(:exact_match) {:return_2}
149
-
150
- subject.foobar(:exact_match)
151
- subject.foobar(:exact_match).should == :return_2
152
- end
153
-
154
- it "raises TimesCalledError when all of the doubles Times Called expectation is satisfied" do
155
- new_double(:exact_match) {:return_1}
156
- new_double(:exact_match) {:return_2}
157
-
158
- subject.foobar(:exact_match)
159
- subject.foobar(:exact_match)
160
- lambda do
161
- subject.foobar(:exact_match)
162
- end.should raise_error(Errors::TimesCalledError)
163
- end
164
-
165
- def new_double(*arguments, &return_value)
166
- double = super()
167
- double.definition.with(*arguments).once.returns(&return_value)
168
- double.should be_terminal
169
- double
170
- end
171
- end
172
-
173
- context "when two or more Doubles with duplicate Wildcard Match ArgumentExpectations exists" do
174
- it "dispatches to Double that have a wildcard match" do
175
- new_double {:return_1}
176
-
177
- subject.foobar(:anything).should == :return_1
178
- end
179
-
180
- it "dispatches to the first Double that has a wildcard match" do
181
- new_double {:return_1}
182
- new_double {:return_2}
183
-
184
- subject.foobar(:anything).should == :return_1
185
- end
186
-
187
- it "dispatches the second Double with a wildcard match
188
- when the first double's Times Called expectation is satisfied" do
189
- new_double {:return_1}
190
- new_double {:return_2}
191
-
192
- subject.foobar(:anything)
193
- subject.foobar(:anything).should == :return_2
194
- end
195
-
196
- it "raises TimesCalledError when all of the doubles Times Called expectation is satisfied" do
197
- new_double {:return_1}
198
- new_double {:return_2}
199
-
200
- subject.foobar(:anything)
201
- subject.foobar(:anything)
202
- lambda do
203
- subject.foobar(:anything)
204
- end.should raise_error(Errors::TimesCalledError)
205
- end
206
-
207
- def new_double(&return_value)
208
- double = super
209
- double.definition.with_any_args.once.returns(&return_value)
210
- double.should be_terminal
211
- double
212
- end
213
- end
214
- end
215
-
216
- describe "method names with !" do
217
- def method_name
218
- :foobar!
219
- end
220
-
221
- context "when the original method uses the passed-in block" do
222
- it "executes the block" do
223
- double = new_double
224
- double.definition.with(1, 2) {:return_value}
225
- subject.foobar!(1, 2).should == :return_value
226
- end
227
- end
228
- end
229
-
230
- describe "method names with ?" do
231
- def method_name
232
- :foobar?
233
- end
234
-
235
- context "when the original method uses the passed-in block" do
236
- it "executes the block" do
237
- double = new_double
238
- double.definition.with(1, 2) {:return_value}
239
- subject.foobar?(1, 2).should == :return_value
240
- end
241
- end
242
- end
243
- end
244
- end