rr 0.10.11 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +5 -0
- data/Gemfile +6 -0
- data/README.rdoc +28 -2
- data/VERSION.yml +3 -3
- data/lib/rr.rb +23 -17
- data/lib/rr/adapters/rr_methods.rb +43 -17
- data/lib/rr/blank_slate.rb +2 -2
- data/lib/rr/class_instance_method_defined.rb +9 -0
- data/lib/rr/double.rb +2 -2
- data/lib/rr/double_definitions/double_definition.rb +29 -16
- data/lib/rr/double_definitions/double_definition_create.rb +52 -86
- data/lib/rr/double_definitions/double_injections/any_instance_of.rb +28 -0
- data/lib/rr/double_definitions/double_injections/instance.rb +16 -0
- data/lib/rr/double_definitions/double_injections/new_instance_of.rb +53 -0
- data/lib/rr/double_definitions/strategies/double_injection/any_instance_of.rb +31 -0
- data/lib/rr/double_definitions/strategies/double_injection/double_injection_strategy.rb +10 -0
- data/lib/rr/double_definitions/strategies/double_injection/instance.rb +17 -0
- data/lib/rr/double_definitions/strategies/double_injection/new_instance_of.rb +37 -0
- data/lib/rr/double_definitions/strategies/implementation/implementation_strategy.rb +0 -5
- data/lib/rr/double_definitions/strategies/implementation/proxy.rb +0 -2
- data/lib/rr/double_definitions/strategies/implementation/strongly_typed_reimplementation.rb +0 -2
- data/lib/rr/double_definitions/strategies/strategy.rb +0 -27
- data/lib/rr/double_definitions/strategies/strategy_methods.rb +53 -0
- data/lib/rr/double_definitions/strategies/verification/dont_allow.rb +0 -2
- data/lib/rr/double_definitions/strategies/verification/mock.rb +0 -2
- data/lib/rr/double_definitions/strategies/verification/stub.rb +0 -2
- data/lib/rr/double_definitions/strategies/verification/verification_strategy.rb +0 -5
- data/lib/rr/hash_with_object_id_key.rb +4 -0
- data/lib/rr/injections/double_injection.rb +94 -71
- data/lib/rr/injections/injection.rb +8 -10
- data/lib/rr/injections/method_missing_injection.rb +13 -20
- data/lib/rr/injections/singleton_method_added_injection.rb +19 -17
- data/lib/rr/method_dispatches/base_method_dispatch.rb +1 -1
- data/lib/rr/method_dispatches/method_dispatch.rb +4 -4
- data/lib/rr/method_dispatches/method_missing_dispatch.rb +17 -14
- data/lib/rr/recorded_calls.rb +1 -1
- data/lib/rr/space.rb +6 -6
- data/lib/rr/times_called_matchers/times_called_matcher.rb +2 -2
- data/scratch.rb +118 -0
- data/spec/api/any_instance_of/all_instances_of_spec.rb +14 -0
- data/spec/api/any_instance_of/any_instance_of_spec.rb +47 -0
- data/spec/api/mock/mock_spec.rb +2 -2
- data/spec/api/new_instance_of/instance_of_spec.rb +15 -0
- data/spec/api/new_instance_of/new_instance_of_spec.rb +61 -0
- data/spec/environment_fixture_setup.rb +3 -2
- data/spec/rr/adapters/rr_methods_space_spec.rb +8 -10
- data/spec/rr/double_definitions/child_double_definition_creator_spec.rb +1 -1
- data/spec/rr/double_definitions/double_definition_create_blank_slate_spec.rb +6 -2
- data/spec/rr/double_definitions/double_definition_create_spec.rb +1 -52
- data/spec/rr/double_injection/double_injection_verify_spec.rb +1 -1
- data/spec/rr/rspec/rspec_adapter_spec.rb +5 -5
- data/spec/rr/space/space_spec.rb +58 -67
- data/spec/spec_helper.rb +2 -2
- metadata +33 -9
- data/lib/rr/double_definitions/strategies/scope/instance.rb +0 -15
- data/lib/rr/double_definitions/strategies/scope/instance_of_class.rb +0 -50
- data/lib/rr/double_definitions/strategies/scope/scope_strategy.rb +0 -15
data/CHANGES
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
1.0.0
|
2
|
+
- Added any_instance_of (aliased by all_instances_of), which binds methods directly to the class (instead of the eigenclass).
|
3
|
+
- Subclasses of a injected class do not have their methods overridden.
|
4
|
+
- any_instance_of and new_instance_of now have a block syntax
|
5
|
+
|
1
6
|
0.10.11
|
2
7
|
- Added RR.blank_slate_whitelist
|
3
8
|
- Fixed class_eval method redefinition warning in jruby
|
data/Gemfile
ADDED
data/README.rdoc
CHANGED
@@ -213,9 +213,33 @@ renders the partial.
|
|
213
213
|
html
|
214
214
|
end
|
215
215
|
|
216
|
-
===
|
217
|
-
|
216
|
+
=== any_instance_of
|
217
|
+
Allows stubs to be added to all instances of a class. It works by binding to methods from the class itself, rather than the eigenclass.
|
218
|
+
This allows all instances (excluding instances with the method redefined in the eigenclass) to get the change.
|
218
219
|
|
220
|
+
Due to Ruby runtime limitations, mocks will not work as expected. It's not obviously feasible (without an ObjectSpace lookup) to support all of RR's methods (such as mocking).
|
221
|
+
ObjectSpace is not readily supported in jRuby, since it causes general slowness in the intreperter.
|
222
|
+
I'm of the opinion that test speed is more important than having mocks on all instances of a class.
|
223
|
+
If there is another solution, I'd be willing to add it.
|
224
|
+
|
225
|
+
any_instance_of(User) do |u|
|
226
|
+
stub(u).valid? {false}
|
227
|
+
end
|
228
|
+
# or
|
229
|
+
any_instance_of(User, :valid? => false)
|
230
|
+
# or
|
231
|
+
any_instance_of(User, :valid? => lambda {false})
|
232
|
+
|
233
|
+
=== new_instance_of
|
234
|
+
Stubs the new method of the class and allows doubles to be bound to new instances.
|
235
|
+
|
236
|
+
Mocks can be used, because new instances are deterministically bound.
|
237
|
+
|
238
|
+
new_instance_of(User) do |u|
|
239
|
+
mock(u).valid? {false}
|
240
|
+
end
|
241
|
+
|
242
|
+
# Deprecated syntax
|
219
243
|
mock.instance_of(User).valid? {false}
|
220
244
|
|
221
245
|
=== Spies
|
@@ -338,7 +362,9 @@ If you have directly contributed to RR and I missed you in this list, please let
|
|
338
362
|
* Dave Myron for a bug report
|
339
363
|
* David Chelimsky for encouragement to make the RR framework, for developing the Rspec mock framework, syntax ideas, and patches
|
340
364
|
* Daniel Sudol for identifing performance issues with RR
|
365
|
+
* Dmitry Ratnikov for patches
|
341
366
|
* Felix Morio for pairing with me
|
367
|
+
* Gabriel Horner for patches
|
342
368
|
* Gerard Meszaros for his excellent book "xUnit Test Patterns"
|
343
369
|
* James Mead for developing Mocha
|
344
370
|
* Jeff Whitmire for documentation suggestions
|
data/VERSION.yml
CHANGED
data/lib/rr.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
dir = File.dirname(__FILE__)
|
2
|
-
require 'rubygems'
|
3
2
|
require 'forwardable'
|
4
3
|
|
5
4
|
require "#{dir}/rr/blank_slate"
|
@@ -17,6 +16,27 @@ require "#{dir}/rr/errors/spy_verification_errors/double_injection_not_found_err
|
|
17
16
|
require "#{dir}/rr/errors/spy_verification_errors/invocation_count_error"
|
18
17
|
|
19
18
|
require "#{dir}/rr/space"
|
19
|
+
|
20
|
+
require "#{dir}/rr/double_definitions/strategies/strategy"
|
21
|
+
require "#{dir}/rr/double_definitions/strategies/strategy_methods"
|
22
|
+
require "#{dir}/rr/double_definitions/strategies/verification/verification_strategy"
|
23
|
+
require "#{dir}/rr/double_definitions/strategies/verification/mock"
|
24
|
+
require "#{dir}/rr/double_definitions/strategies/verification/stub"
|
25
|
+
require "#{dir}/rr/double_definitions/strategies/verification/dont_allow"
|
26
|
+
require "#{dir}/rr/double_definitions/strategies/implementation/implementation_strategy"
|
27
|
+
require "#{dir}/rr/double_definitions/strategies/implementation/reimplementation"
|
28
|
+
require "#{dir}/rr/double_definitions/strategies/implementation/strongly_typed_reimplementation"
|
29
|
+
require "#{dir}/rr/double_definitions/strategies/implementation/proxy"
|
30
|
+
require "#{dir}/rr/double_definitions/strategies/double_injection/double_injection_strategy"
|
31
|
+
require "#{dir}/rr/double_definitions/strategies/double_injection/instance"
|
32
|
+
require "#{dir}/rr/double_definitions/strategies/double_injection/any_instance_of"
|
33
|
+
require "#{dir}/rr/double_definitions/strategies/double_injection/new_instance_of"
|
34
|
+
require "#{dir}/rr/adapters/rr_methods"
|
35
|
+
require "#{dir}/rr/double_definitions/double_injections/instance"
|
36
|
+
require "#{dir}/rr/double_definitions/double_injections/any_instance_of"
|
37
|
+
require "#{dir}/rr/double_definitions/double_injections/new_instance_of"
|
38
|
+
require "#{dir}/rr/double_definitions/double_definition"
|
39
|
+
|
20
40
|
require "#{dir}/rr/injections/injection"
|
21
41
|
require "#{dir}/rr/injections/double_injection"
|
22
42
|
require "#{dir}/rr/injections/method_missing_injection"
|
@@ -27,26 +47,13 @@ require "#{dir}/rr/method_dispatches/method_missing_dispatch"
|
|
27
47
|
require "#{dir}/rr/hash_with_object_id_key"
|
28
48
|
require "#{dir}/rr/recorded_calls"
|
29
49
|
require "#{dir}/rr/proc_from_block"
|
50
|
+
require "#{dir}/rr/class_instance_method_defined"
|
30
51
|
|
31
52
|
require "#{dir}/rr/double_definitions/double_definition_create_blank_slate"
|
32
53
|
require "#{dir}/rr/double_definitions/double_definition_create"
|
33
54
|
require "#{dir}/rr/double_definitions/child_double_definition_create"
|
34
|
-
require "#{dir}/rr/adapters/rr_methods"
|
35
55
|
|
36
56
|
require "#{dir}/rr/double"
|
37
|
-
require "#{dir}/rr/double_definitions/double_definition"
|
38
|
-
require "#{dir}/rr/double_definitions/strategies/strategy"
|
39
|
-
require "#{dir}/rr/double_definitions/strategies/verification/verification_strategy"
|
40
|
-
require "#{dir}/rr/double_definitions/strategies/verification/mock"
|
41
|
-
require "#{dir}/rr/double_definitions/strategies/verification/stub"
|
42
|
-
require "#{dir}/rr/double_definitions/strategies/verification/dont_allow"
|
43
|
-
require "#{dir}/rr/double_definitions/strategies/implementation/implementation_strategy"
|
44
|
-
require "#{dir}/rr/double_definitions/strategies/implementation/reimplementation"
|
45
|
-
require "#{dir}/rr/double_definitions/strategies/implementation/strongly_typed_reimplementation"
|
46
|
-
require "#{dir}/rr/double_definitions/strategies/implementation/proxy"
|
47
|
-
require "#{dir}/rr/double_definitions/strategies/scope/scope_strategy"
|
48
|
-
require "#{dir}/rr/double_definitions/strategies/scope/instance"
|
49
|
-
require "#{dir}/rr/double_definitions/strategies/scope/instance_of_class"
|
50
57
|
require "#{dir}/rr/double_matches"
|
51
58
|
|
52
59
|
require "#{dir}/rr/expectations/argument_equality_expectation"
|
@@ -84,12 +91,11 @@ module RR
|
|
84
91
|
class << self
|
85
92
|
include Adapters::RRMethods
|
86
93
|
(RR::Space.instance_methods - Object.instance_methods).each do |method_name|
|
87
|
-
|
94
|
+
class_eval((<<-METHOD), __FILE__, __LINE__ + 1)
|
88
95
|
def #{method_name}(*args, &block)
|
89
96
|
RR::Space.instance.__send__(:#{method_name}, *args, &block)
|
90
97
|
end
|
91
98
|
METHOD
|
92
|
-
class_eval(returns_method, __FILE__, __LINE__ - 4)
|
93
99
|
end
|
94
100
|
end
|
95
101
|
end
|
@@ -1,22 +1,40 @@
|
|
1
1
|
module RR
|
2
2
|
module Adapters
|
3
3
|
module RRMethods
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
4
|
+
include ::RR::DoubleDefinitions::Strategies::StrategyMethods
|
5
|
+
def mock(subject=DoubleDefinitions::DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
|
6
|
+
double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new
|
7
|
+
double_definition_create.mock(subject, method_name, &definition_eval_block)
|
8
|
+
end
|
9
|
+
|
10
|
+
def stub(subject=DoubleDefinitions::DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
|
11
|
+
double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new
|
12
|
+
double_definition_create.stub(subject, method_name, &definition_eval_block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def dont_allow(subject=DoubleDefinitions::DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
|
16
|
+
double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new
|
17
|
+
double_definition_create.dont_allow(subject, method_name, &definition_eval_block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def proxy(subject=DoubleDefinitions::DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
|
21
|
+
double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new
|
22
|
+
double_definition_create.proxy(subject, method_name, &definition_eval_block)
|
23
|
+
end
|
24
|
+
|
25
|
+
def strong(subject=DoubleDefinitions::DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
|
26
|
+
double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new
|
27
|
+
double_definition_create.strong(subject, method_name, &definition_eval_block)
|
28
|
+
end
|
29
|
+
|
30
|
+
def any_instance_of(subject=DoubleDefinitions::DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
|
31
|
+
double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new
|
32
|
+
double_definition_create.any_instance_of(subject, method_name, &definition_eval_block)
|
33
|
+
end
|
34
|
+
|
35
|
+
def instance_of(subject=DoubleDefinitions::DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
|
36
|
+
double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new
|
37
|
+
double_definition_create.instance_of(subject, method_name, &definition_eval_block)
|
20
38
|
end
|
21
39
|
|
22
40
|
# Verifies all the DoubleInjection objects have met their
|
@@ -102,7 +120,7 @@ module RR
|
|
102
120
|
|
103
121
|
def spy(subject)
|
104
122
|
methods_to_stub = subject.public_methods.map {|method_name| method_name.to_sym} -
|
105
|
-
[:methods, :==, :__send__, :__id__, :object_id]
|
123
|
+
[:methods, :==, :__send__, :__id__, :object_id, :class]
|
106
124
|
methods_to_stub.each do |method|
|
107
125
|
stub.proxy(subject, method)
|
108
126
|
end
|
@@ -112,6 +130,14 @@ module RR
|
|
112
130
|
RR::SpyVerificationProxy.new(subject)
|
113
131
|
end
|
114
132
|
|
133
|
+
def new_instance_of(*args, &block)
|
134
|
+
RR::DoubleDefinitions::DoubleInjections::NewInstanceOf.call(*args, &block)
|
135
|
+
end
|
136
|
+
|
137
|
+
def any_instance_of(*args, &block)
|
138
|
+
RR::DoubleDefinitions::DoubleInjections::AnyInstanceOf.call(*args, &block)
|
139
|
+
end
|
140
|
+
|
115
141
|
instance_methods.each do |name|
|
116
142
|
alias_method "rr_#{name}", name
|
117
143
|
end
|
data/lib/rr/blank_slate.rb
CHANGED
@@ -0,0 +1,9 @@
|
|
1
|
+
module RR
|
2
|
+
module ClassInstanceMethodDefined
|
3
|
+
def self.call(klass, instance_method, include_super=true)
|
4
|
+
klass.instance_methods(include_super).detect {|method_name| method_name.to_sym == instance_method.to_sym} ||
|
5
|
+
klass.protected_instance_methods(include_super).detect {|method_name| method_name.to_sym == instance_method.to_sym} ||
|
6
|
+
klass.private_instance_methods(include_super).detect {|method_name| method_name.to_sym == instance_method.to_sym}
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
data/lib/rr/double.rb
CHANGED
@@ -3,7 +3,7 @@ module RR
|
|
3
3
|
# It has the ArgumentEqualityExpectation, TimesCalledExpectation,
|
4
4
|
# and the implementation.
|
5
5
|
class Double
|
6
|
-
|
6
|
+
extend(Module.new do
|
7
7
|
def formatted_name(method_name, args)
|
8
8
|
formatted_errors = args.collect {|arg| arg.inspect}.join(', ')
|
9
9
|
"#{method_name}(#{formatted_errors})"
|
@@ -14,7 +14,7 @@ module RR
|
|
14
14
|
"- #{formatted_name(double.method_name, double.expected_arguments)}"
|
15
15
|
end.join("\n")
|
16
16
|
end
|
17
|
-
end
|
17
|
+
end)
|
18
18
|
|
19
19
|
attr_reader :times_called, :double_injection, :definition, :times_called_expectation
|
20
20
|
include Space::Reader
|
@@ -1,22 +1,6 @@
|
|
1
1
|
module RR
|
2
2
|
module DoubleDefinitions
|
3
3
|
class DoubleDefinition #:nodoc:
|
4
|
-
class << self
|
5
|
-
def register_strategy_class(strategy_class, method_name)
|
6
|
-
class_eval((<<-CLASS), __FILE__, __LINE__ + 1)
|
7
|
-
def #{method_name}(subject=DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
|
8
|
-
ChildDoubleDefinitionCreate.new(self).#{method_name}(subject, method_name, &definition_eval_block)
|
9
|
-
end
|
10
|
-
CLASS
|
11
|
-
|
12
|
-
class_eval((<<-CLASS), __FILE__, __LINE__ + 1)
|
13
|
-
def #{method_name}!(method_name=nil, &definition_eval_block)
|
14
|
-
ChildDoubleDefinitionCreate.new(self).#{method_name}!(method_name, &definition_eval_block)
|
15
|
-
end
|
16
|
-
CLASS
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
4
|
ORIGINAL_METHOD = Object.new
|
21
5
|
attr_accessor(
|
22
6
|
:argument_expectation,
|
@@ -349,6 +333,35 @@ module RR
|
|
349
333
|
end
|
350
334
|
end
|
351
335
|
include StateQueryMethods
|
336
|
+
include ::RR::DoubleDefinitions::Strategies::StrategyMethods
|
337
|
+
|
338
|
+
def mock(subject=DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
|
339
|
+
ChildDoubleDefinitionCreate.new(self).mock(subject, method_name, &definition_eval_block)
|
340
|
+
end
|
341
|
+
|
342
|
+
def stub(subject=DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
|
343
|
+
ChildDoubleDefinitionCreate.new(self).stub(subject, method_name, &definition_eval_block)
|
344
|
+
end
|
345
|
+
|
346
|
+
def dont_allow(subject=DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
|
347
|
+
ChildDoubleDefinitionCreate.new(self).dont_allow(subject, method_name, &definition_eval_block)
|
348
|
+
end
|
349
|
+
|
350
|
+
def proxy(subject=DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
|
351
|
+
ChildDoubleDefinitionCreate.new(self).proxy(subject, method_name, &definition_eval_block)
|
352
|
+
end
|
353
|
+
|
354
|
+
def strong(subject=DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
|
355
|
+
ChildDoubleDefinitionCreate.new(self).strong(subject, method_name, &definition_eval_block)
|
356
|
+
end
|
357
|
+
|
358
|
+
def any_instance_of(subject=DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
|
359
|
+
ChildDoubleDefinitionCreate.new(self).any_instance_of(subject, method_name, &definition_eval_block)
|
360
|
+
end
|
361
|
+
|
362
|
+
def instance_of(subject=DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
|
363
|
+
ChildDoubleDefinitionCreate.new(self).instance_of(subject, method_name, &definition_eval_block)
|
364
|
+
end
|
352
365
|
end
|
353
366
|
end
|
354
367
|
end
|
@@ -1,82 +1,51 @@
|
|
1
1
|
module RR
|
2
2
|
module DoubleDefinitions
|
3
3
|
class DoubleDefinitionCreate # :nodoc
|
4
|
-
|
5
|
-
def
|
6
|
-
|
7
|
-
|
8
|
-
self.add_verification_strategy(#{strategy_class.name}, subject, method_name, &definition_eval_block)
|
4
|
+
extend(Module.new do
|
5
|
+
def default_double_injection_strategy
|
6
|
+
@default_double_injection_strategy ||= lambda do |double_injection_create|
|
7
|
+
Strategies::DoubleInjection::Instance.new(double_injection_create)
|
9
8
|
end
|
10
|
-
CLASS
|
11
|
-
|
12
|
-
class_eval((<<-CLASS), __FILE__, __LINE__ + 1)
|
13
|
-
def #{strategy_method_name}!(method_name=nil, &definition_eval_block)
|
14
|
-
#{strategy_method_name}(Object.new, method_name, &definition_eval_block)
|
15
|
-
end
|
16
|
-
CLASS
|
17
9
|
end
|
18
|
-
|
19
|
-
def register_implementation_strategy_class(strategy_class, strategy_method_name)
|
20
|
-
class_eval((<<-CLASS), __FILE__, __LINE__ + 1)
|
21
|
-
def #{strategy_method_name}(subject=NO_SUBJECT, method_name=nil, &definition_eval_block)
|
22
|
-
self.add_implementation_strategy(#{strategy_class.name}, subject, method_name, &definition_eval_block)
|
23
|
-
end
|
24
|
-
CLASS
|
25
10
|
|
26
|
-
|
27
|
-
|
28
|
-
|
11
|
+
def set_default_double_injection_strategy(strategy_lambda)
|
12
|
+
original_strategy_lambda = default_double_injection_strategy
|
13
|
+
begin
|
14
|
+
@default_double_injection_strategy = strategy_lambda
|
15
|
+
yield
|
16
|
+
ensure
|
17
|
+
@default_double_injection_strategy = original_strategy_lambda
|
29
18
|
end
|
30
|
-
CLASS
|
31
19
|
end
|
20
|
+
end)
|
32
21
|
|
33
|
-
|
34
|
-
class_eval((<<-CLASS), __FILE__, __LINE__ + 1)
|
35
|
-
def #{strategy_method_name}(subject=NO_SUBJECT, method_name=nil, &definition_eval_block)
|
36
|
-
self.add_scope_strategy(#{strategy_class.name}, subject, method_name, &definition_eval_block)
|
37
|
-
end
|
38
|
-
CLASS
|
39
|
-
|
40
|
-
class_eval((<<-CLASS), __FILE__, __LINE__ + 1)
|
41
|
-
def #{strategy_method_name}!(method_name=nil, &definition_eval_block)
|
42
|
-
#{strategy_method_name}(Object.new, method_name, &definition_eval_block)
|
43
|
-
end
|
44
|
-
CLASS
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
attr_reader :subject,
|
49
|
-
:verification_strategy,
|
50
|
-
:implementation_strategy,
|
51
|
-
:scope_strategy
|
22
|
+
attr_reader :subject, :verification_strategy, :implementation_strategy, :double_injection_strategy
|
52
23
|
NO_SUBJECT = Object.new
|
53
24
|
|
54
25
|
include Space::Reader
|
55
26
|
|
56
27
|
def initialize
|
57
|
-
@verification_strategy =
|
28
|
+
@verification_strategy = Strategies::Verification::Stub.new(self)
|
58
29
|
@implementation_strategy = Strategies::Implementation::Reimplementation.new(self)
|
59
|
-
@
|
30
|
+
@double_injection_strategy = self.class.default_double_injection_strategy.call(self)
|
60
31
|
end
|
61
32
|
|
62
33
|
def call(method_name, *args, &handler)
|
63
|
-
raise DoubleDefinitionCreateError if no_subject?
|
64
34
|
definition = DoubleDefinition.new(self)
|
65
|
-
verification_strategy || no_strategy_error
|
66
35
|
verification_strategy.call(definition, method_name, args, handler)
|
67
36
|
implementation_strategy.call(definition, method_name, args, handler)
|
68
|
-
|
37
|
+
double_injection_strategy.call(definition, method_name, args, handler)
|
69
38
|
definition
|
70
39
|
end
|
71
|
-
|
40
|
+
|
72
41
|
def root_subject
|
73
42
|
subject
|
74
43
|
end
|
75
|
-
|
44
|
+
|
76
45
|
def method_name
|
77
46
|
@verification_strategy.method_name
|
78
47
|
end
|
79
|
-
|
48
|
+
|
80
49
|
module StrategySetupMethods
|
81
50
|
def no_subject?
|
82
51
|
subject.__id__ === NO_SUBJECT.__id__
|
@@ -95,9 +64,9 @@ module RR
|
|
95
64
|
end
|
96
65
|
end
|
97
66
|
|
98
|
-
def
|
67
|
+
def add_double_injection_strategy(double_injection_strategy_class, subject=NO_SUBJECT, method_name=nil, &definition_eval_block)
|
99
68
|
add_strategy(subject, method_name, definition_eval_block) do
|
100
|
-
self.
|
69
|
+
self.double_injection_strategy = double_injection_strategy_class.new(self)
|
101
70
|
end
|
102
71
|
end
|
103
72
|
|
@@ -119,56 +88,53 @@ module RR
|
|
119
88
|
end
|
120
89
|
|
121
90
|
def verification_strategy=(verification_strategy)
|
122
|
-
verify_no_verification_strategy
|
123
|
-
verify_not_proxy_and_dont_allow(verification_strategy, implementation_strategy)
|
124
91
|
@verification_strategy = verification_strategy
|
125
92
|
verification_strategy
|
126
93
|
end
|
127
94
|
|
128
95
|
def implementation_strategy=(implementation_strategy)
|
129
|
-
verify_not_proxy_and_dont_allow(verification_strategy, implementation_strategy)
|
130
96
|
@implementation_strategy = implementation_strategy
|
131
97
|
end
|
132
98
|
|
133
|
-
def
|
134
|
-
|
135
|
-
@scope_strategy = scope_strategy
|
99
|
+
def double_injection_strategy=(double_injection_strategy)
|
100
|
+
@double_injection_strategy = double_injection_strategy
|
136
101
|
end
|
102
|
+
end
|
103
|
+
include StrategySetupMethods
|
137
104
|
|
138
|
-
|
139
|
-
|
140
|
-
end
|
105
|
+
class DoubleDefinitionCreateError < Errors::RRError
|
106
|
+
end
|
141
107
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
end
|
108
|
+
# Verification Strategies
|
109
|
+
include ::RR::DoubleDefinitions::Strategies::StrategyMethods
|
110
|
+
def mock(subject=NO_SUBJECT, method_name=nil, &definition_eval_block)
|
111
|
+
self.add_verification_strategy(::RR::DoubleDefinitions::Strategies::Verification::Mock, subject, method_name, &definition_eval_block)
|
112
|
+
end
|
148
113
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
implementation_strategy.is_a?(Strategies::Implementation::Proxy)
|
153
|
-
end
|
114
|
+
def stub(subject=NO_SUBJECT, method_name=nil, &definition_eval_block)
|
115
|
+
self.add_verification_strategy(::RR::DoubleDefinitions::Strategies::Verification::Stub, subject, method_name, &definition_eval_block)
|
116
|
+
end
|
154
117
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
"Doubles cannot be proxied when using dont_allow strategy"
|
159
|
-
)
|
160
|
-
end
|
118
|
+
def dont_allow(subject=NO_SUBJECT, method_name=nil, &definition_eval_block)
|
119
|
+
self.add_verification_strategy(::RR::DoubleDefinitions::Strategies::Verification::DontAllow, subject, method_name, &definition_eval_block)
|
120
|
+
end
|
161
121
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
"This Double has no strategy"
|
166
|
-
)
|
167
|
-
end
|
122
|
+
# Implementation Strategies
|
123
|
+
def proxy(subject=NO_SUBJECT, method_name=nil, &definition_eval_block)
|
124
|
+
self.add_implementation_strategy(::RR::DoubleDefinitions::Strategies::Implementation::Proxy, subject, method_name, &definition_eval_block)
|
168
125
|
end
|
169
|
-
include StrategySetupMethods
|
170
126
|
|
171
|
-
|
127
|
+
def strong(subject=NO_SUBJECT, method_name=nil, &definition_eval_block)
|
128
|
+
self.add_implementation_strategy(::RR::DoubleDefinitions::Strategies::Implementation::StronglyTypedReimplementation, subject, method_name, &definition_eval_block)
|
129
|
+
end
|
130
|
+
|
131
|
+
# DoubleInjection Strategies
|
132
|
+
def any_instance_of(subject=NO_SUBJECT, method_name=nil, &definition_eval_block)
|
133
|
+
self.add_double_injection_strategy(::RR::DoubleDefinitions::Strategies::DoubleInjection::AnyInstanceOf, subject, method_name, &definition_eval_block)
|
134
|
+
end
|
135
|
+
|
136
|
+
def instance_of(subject=NO_SUBJECT, method_name=nil, &definition_eval_block)
|
137
|
+
self.add_double_injection_strategy(::RR::DoubleDefinitions::Strategies::DoubleInjection::NewInstanceOf, subject, method_name, &definition_eval_block)
|
172
138
|
end
|
173
139
|
end
|
174
140
|
end
|