rr 0.10.2 → 0.10.4

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