rr 0.10.10 → 0.10.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/CHANGES +4 -0
  2. data/VERSION.yml +1 -1
  3. data/lib/rr.rb +5 -3
  4. data/lib/rr/adapters/rr_methods.rb +5 -5
  5. data/lib/rr/blank_slate.rb +17 -0
  6. data/lib/rr/double_definitions/{child_double_definition_creator.rb → child_double_definition_create.rb} +1 -1
  7. data/lib/rr/double_definitions/double_definition.rb +13 -11
  8. data/lib/rr/double_definitions/{double_definition_creator.rb → double_definition_create.rb} +52 -43
  9. data/lib/rr/double_definitions/double_definition_create_blank_slate.rb +26 -0
  10. data/lib/rr/double_definitions/strategies/implementation/implementation_strategy.rb +2 -2
  11. data/lib/rr/double_definitions/strategies/scope/instance.rb +1 -1
  12. data/lib/rr/double_definitions/strategies/scope/instance_of_class.rb +6 -6
  13. data/lib/rr/double_definitions/strategies/scope/scope_strategy.rb +2 -2
  14. data/lib/rr/double_definitions/strategies/strategy.rb +15 -16
  15. data/lib/rr/double_definitions/strategies/verification/mock.rb +1 -1
  16. data/lib/rr/double_definitions/strategies/verification/stub.rb +1 -1
  17. data/lib/rr/double_definitions/strategies/verification/verification_strategy.rb +2 -2
  18. data/lib/rr/injections/double_injection.rb +59 -4
  19. data/lib/rr/injections/injection.rb +6 -0
  20. data/lib/rr/injections/method_missing_injection.rb +13 -1
  21. data/lib/rr/injections/singleton_method_added_injection.rb +14 -3
  22. data/lib/rr/method_dispatches/base_method_dispatch.rb +2 -2
  23. data/lib/rr/method_dispatches/method_missing_dispatch.rb +2 -2
  24. data/lib/rr/recorded_calls.rb +1 -1
  25. data/lib/rr/space.rb +17 -68
  26. data/lib/rr/spy_verification_proxy.rb +1 -6
  27. data/spec/rr/adapters/rr_methods_creator_spec.rb +9 -21
  28. data/spec/rr/adapters/rr_methods_space_spec.rb +10 -25
  29. data/spec/rr/double_definitions/child_double_definition_creator_spec.rb +16 -16
  30. data/spec/rr/double_definitions/double_definition_create_blank_slate_spec.rb +87 -0
  31. data/spec/rr/double_definitions/{double_definition_creator_spec.rb → double_definition_create_spec.rb} +64 -72
  32. data/spec/rr/double_injection/double_injection_verify_spec.rb +2 -2
  33. data/spec/rr/expectations/times_called_expectation/times_called_expectation_any_times_spec.rb +5 -29
  34. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_least_spec.rb +7 -39
  35. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_most_spec.rb +19 -47
  36. data/spec/rr/expectations/times_called_expectation/times_called_expectation_helper.rb +1 -9
  37. data/spec/rr/expectations/times_called_expectation/times_called_expectation_integer_spec.rb +18 -64
  38. data/spec/rr/expectations/times_called_expectation/times_called_expectation_proc_spec.rb +7 -53
  39. data/spec/rr/expectations/times_called_expectation/times_called_expectation_range_spec.rb +12 -56
  40. data/spec/rr/rspec/rspec_adapter_spec.rb +8 -11
  41. data/spec/rr/space/space_spec.rb +72 -212
  42. data/spec/spec_helper.rb +0 -76
  43. data/spec/spy_verification_spec.rb +1 -1
  44. metadata +8 -11
  45. data/lib/rr/double_definitions/double_definition_creator_proxy.rb +0 -37
  46. data/ruby_19_spec.rb +0 -12
  47. data/spec/rr/double_definitions/double_definition_creator_proxy_spec.rb +0 -124
  48. data/spec/rr/double_definitions/double_definition_spec.rb +0 -1168
  49. data/spec/rr/double_spec.rb +0 -361
  50. data/spec/rr/expectations/times_called_expectation/times_called_expectation_spec.rb +0 -38
@@ -12,7 +12,7 @@ module RR
12
12
  # or
13
13
  # proxy.mock(subject).method_name_1
14
14
  #
15
- # When passed the subject, a DoubleDefinitionCreatorProxy is returned. Passing
15
+ # When passed the subject, a DoubleDefinitionCreateBlankSlate is returned. Passing
16
16
  # a method with arguments to the proxy will set up expectations that
17
17
  # the a call to the subject's method with the arguments will happen,
18
18
  # and return the prescribed value.
@@ -12,7 +12,7 @@ module RR
12
12
  # or
13
13
  # proxy.stub(subject).method_name_1
14
14
  #
15
- # When passed the subject, a DoubleDefinitionCreatorProxy is returned. Passing
15
+ # When passed the subject, a DoubleDefinitionCreateBlankSlate is returned. Passing
16
16
  # a method with arguments to the proxy will set up expectations that
17
17
  # the a call to the subject's method with the arguments will happen,
18
18
  # and return the prescribed value.
@@ -4,8 +4,8 @@ module RR
4
4
  module Verification
5
5
  class VerificationStrategy < Strategy
6
6
  class << self
7
- def register_self_at_double_definition_creator(domain_name)
8
- DoubleDefinitionCreator.register_verification_strategy_class(self, domain_name)
7
+ def register_self_at_double_definition_create(strategy_method_name)
8
+ DoubleDefinitionCreate.register_verification_strategy_class(self, strategy_method_name)
9
9
  end
10
10
  end
11
11
  end
@@ -4,6 +4,57 @@ module RR
4
4
  # A double_injection has 0 to many Double objects. Each Double
5
5
  # has Argument Expectations and Times called Expectations.
6
6
  class DoubleInjection < Injection
7
+ class << self
8
+ def create(subject, method_name)
9
+ instances[subject][method_name.to_sym] ||= begin
10
+ new(subject, method_name.to_sym, (class << subject; self; end)).bind
11
+ end
12
+ end
13
+
14
+ def exists?(subject, method_name)
15
+ instances.include?(subject) && instances[subject].include?(method_name.to_sym)
16
+ end
17
+
18
+ def reset
19
+ instances.each do |subject, method_double_map|
20
+ method_double_map.keys.each do |method_name|
21
+ reset_double(subject, method_name)
22
+ end
23
+ end
24
+ end
25
+
26
+ def verify(*subjects)
27
+ subjects = Injections::DoubleInjection.instances.keys if subjects.empty?
28
+ subjects.each do |subject|
29
+ instances.include?(subject) &&
30
+ instances[subject].keys.each do |method_name|
31
+ verify_double(subject, method_name)
32
+ end &&
33
+ instances.delete(subject)
34
+ end
35
+ end
36
+
37
+ # Verifies the DoubleInjection for the passed in subject and method_name.
38
+ def verify_double(subject, method_name)
39
+ Injections::DoubleInjection.instances[subject][method_name].verify
40
+ ensure
41
+ reset_double subject, method_name
42
+ end
43
+
44
+ # Resets the DoubleInjection for the passed in subject and method_name.
45
+ def reset_double(subject, method_name)
46
+ double_injection = Injections::DoubleInjection.instances[subject].delete(method_name)
47
+ Injections::DoubleInjection.instances.delete(subject) if Injections::DoubleInjection.instances[subject].empty?
48
+ double_injection.reset
49
+ end
50
+
51
+ def instances
52
+ @instances ||= HashWithObjectIdKey.new do |hash, subject_object|
53
+ hash.set_with_object_id(subject_object, {})
54
+ end
55
+ end
56
+ end
57
+
7
58
  attr_reader :subject_class, :method_name, :doubles
8
59
 
9
60
  MethodArguments = Struct.new(:arguments, :block)
@@ -34,8 +85,8 @@ module RR
34
85
  bind_method_with_alias
35
86
  end
36
87
  else
37
- space.method_missing_injection(subject)
38
- space.singleton_method_added_injection(subject)
88
+ Injections::MethodMissingInjection.create(subject)
89
+ Injections::SingletonMethodAddedInjection.create(subject)
39
90
  end
40
91
  else
41
92
  bind_method
@@ -50,6 +101,7 @@ module RR
50
101
  double.verify
51
102
  end
52
103
  end
104
+
53
105
  # RR::DoubleInjection#reset removes the injected dispatcher method.
54
106
 
55
107
  # It binds the original method implementation on the subject
@@ -100,7 +152,10 @@ module RR
100
152
 
101
153
  protected
102
154
  def subject_is_proxy_for_method?(method_name_in_question)
103
- !(class << @subject; self; end).
155
+ !(
156
+ class << @subject;
157
+ self;
158
+ end).
104
159
  instance_methods.
105
160
  detect {|method_name| method_name.to_sym == method_name_in_question.to_sym}
106
161
  end
@@ -122,7 +177,7 @@ module RR
122
177
  subject_class.class_eval(<<-METHOD, __FILE__, __LINE__ + 1)
123
178
  def #{@method_name}(*args, &block)
124
179
  arguments = MethodArguments.new(args, block)
125
- RR::Space.double_injection(#{subject}, :#{@method_name}).dispatch_method(arguments.arguments, arguments.block)
180
+ RR::Injections::DoubleInjection.create(#{subject}, :#{@method_name}).dispatch_method(arguments.arguments, arguments.block)
126
181
  end
127
182
  METHOD
128
183
  end
@@ -1,6 +1,12 @@
1
1
  module RR
2
2
  module Injections
3
3
  class Injection
4
+ class << self
5
+ def instances
6
+ @instances ||= HashWithObjectIdKey.new
7
+ end
8
+ end
9
+
4
10
  include Space::Reader
5
11
 
6
12
  attr_reader :subject
@@ -1,6 +1,18 @@
1
1
  module RR
2
2
  module Injections
3
3
  class MethodMissingInjection < Injection
4
+ class << self
5
+ def create(subject)
6
+ instances[subject] ||= begin
7
+ new(subject).bind
8
+ end
9
+ end
10
+
11
+ def exists?(subject)
12
+ instances.include?(subject)
13
+ end
14
+ end
15
+
4
16
  def initialize(subject)
5
17
  @subject = subject
6
18
  @placeholder_method_defined = false
@@ -48,7 +60,7 @@ module RR
48
60
  def bind_method
49
61
  returns_method = <<-METHOD
50
62
  def method_missing(method_name, *args, &block)
51
- RR::Space.method_missing_injection(self).dispatch_method(method_name, args, block)
63
+ RR::Injections::MethodMissingInjection.create(self).dispatch_method(method_name, args, block)
52
64
  end
53
65
  METHOD
54
66
  subject_class.class_eval(returns_method, __FILE__, __LINE__ - 4)
@@ -1,6 +1,18 @@
1
1
  module RR
2
2
  module Injections
3
3
  class SingletonMethodAddedInjection < Injection
4
+ class << self
5
+ def create(subject)
6
+ instances[subject] ||= begin
7
+ new(subject).bind
8
+ end
9
+ end
10
+
11
+ def exists?(subject)
12
+ instances.include?(subject)
13
+ end
14
+ end
15
+
4
16
  def initialize(subject)
5
17
  @subject = subject
6
18
  @placeholder_method_defined = false
@@ -18,12 +30,11 @@ module RR
18
30
  end
19
31
 
20
32
  memoized_subject = subject
21
- memoized_space = space
22
33
  memoized_original_method_alias_name = original_method_alias_name
23
34
  subject_class.__send__(:alias_method, original_method_alias_name, :singleton_method_added)
24
35
  subject_class.__send__(:define_method, :singleton_method_added) do |method_name_arg|
25
- if memoized_space.double_injection_exists?(memoized_subject, method_name_arg)
26
- memoized_space.double_injection(memoized_subject, method_name_arg).send(:deferred_bind_method)
36
+ if Injections::DoubleInjection.exists?(memoized_subject, method_name_arg)
37
+ Injections::DoubleInjection.create(memoized_subject, method_name_arg).send(:deferred_bind_method)
27
38
  end
28
39
  send(memoized_original_method_alias_name, method_name_arg)
29
40
  end
@@ -59,8 +59,8 @@ module RR
59
59
  case return_value
60
60
  when DoubleDefinitions::DoubleDefinition
61
61
  return_value.root_subject
62
- when DoubleDefinitions::DoubleDefinitionCreatorProxy
63
- return_value.__creator__.root_subject
62
+ when DoubleDefinitions::DoubleDefinitionCreateBlankSlate
63
+ return_value.__double_definition_create__.root_subject
64
64
  else
65
65
  return_value
66
66
  end
@@ -13,7 +13,7 @@ module RR
13
13
  end
14
14
 
15
15
  def call
16
- if space.double_injection_exists?(subject, method_name)
16
+ if Injections::DoubleInjection.exists?(subject, method_name)
17
17
  space.record_call(subject, method_name, args, block)
18
18
  @double = find_double_to_attempt
19
19
 
@@ -50,7 +50,7 @@ module RR
50
50
  end
51
51
 
52
52
  def double_injection
53
- space.double_injection(subject, method_name)
53
+ Injections::DoubleInjection.create(subject, method_name)
54
54
  end
55
55
 
56
56
  def_delegators 'self.class', :original_method_missing_alias_name
@@ -40,7 +40,7 @@ module RR
40
40
  attr_accessor :ordered_index
41
41
 
42
42
  def double_injection_exists_error(spy_verification)
43
- unless space.double_injection_exists?(spy_verification.subject, spy_verification.method_name)
43
+ unless Injections::DoubleInjection.exists?(spy_verification.subject, spy_verification.method_name)
44
44
  RR::Errors::SpyVerificationErrors::DoubleInjectionNotFoundError.new(
45
45
  "A Double Injection for the subject and method call:\n" <<
46
46
  "#{spy_verification.subject.inspect}\n" <<
data/lib/rr/space.rb CHANGED
@@ -19,53 +19,14 @@ module RR
19
19
  end
20
20
  end
21
21
 
22
- attr_reader :double_injections, :method_missing_injections, :ordered_doubles, :recorded_calls
22
+ attr_reader :ordered_doubles, :recorded_calls
23
23
  attr_accessor :trim_backtrace
24
24
  def initialize
25
- @double_injections = HashWithObjectIdKey.new do |hash, subject_object|
26
- hash.set_with_object_id(subject_object, {})
27
- end
28
- @method_missing_injections = HashWithObjectIdKey.new
29
- @singleton_method_added_injections = HashWithObjectIdKey.new
30
25
  @ordered_doubles = []
31
26
  @trim_backtrace = false
32
27
  @recorded_calls = RR::RecordedCalls.new
33
28
  end
34
29
 
35
- # Reuses or creates, if none exists, a DoubleInjection for the passed
36
- # in subject and method_name.
37
- # When a DoubleInjection is created, it binds the dispatcher to the
38
- # subject.
39
- def double_injection(subject, method_name)
40
- @double_injections[subject][method_name.to_sym] ||= begin
41
- Injections::DoubleInjection.new(subject, method_name.to_sym, (class << subject; self; end)).bind
42
- end
43
- end
44
-
45
- def double_injection_exists?(subject, method_name)
46
- @double_injections.include?(subject) && @double_injections[subject].include?(method_name.to_sym)
47
- end
48
-
49
- def method_missing_injection(subject)
50
- @method_missing_injections[subject] ||= begin
51
- Injections::MethodMissingInjection.new(subject).bind
52
- end
53
- end
54
-
55
- def method_missing_injection_exists?(subject)
56
- @method_missing_injections.include?(subject)
57
- end
58
-
59
- def singleton_method_added_injection(subject)
60
- @singleton_method_added_injections[subject] ||= begin
61
- Injections::SingletonMethodAddedInjection.new(subject).bind
62
- end
63
- end
64
-
65
- def singleton_method_added_injection_exists?(subject)
66
- @singleton_method_added_injections.include?(subject)
67
- end
68
-
69
30
  # Registers the ordered Double to be verified.
70
31
  def register_ordered_double(double)
71
32
  @ordered_doubles << double unless ordered_doubles.include?(double)
@@ -90,20 +51,15 @@ module RR
90
51
 
91
52
  # Verifies all the DoubleInjection objects have met their
92
53
  # TimesCalledExpectations.
93
- def verify_doubles(*objects)
94
- objects = @double_injections.keys if objects.empty?
95
- objects.each do |subject|
96
- @double_injections[subject].keys.each do |method_name|
97
- verify_double(subject, method_name)
98
- end
99
- end
54
+ def verify_doubles(*subjects)
55
+ Injections::DoubleInjection.verify(*subjects)
100
56
  end
101
57
  alias_method :verify, :verify_doubles
102
58
 
103
59
  # Resets the registered Doubles and ordered Doubles
104
60
  def reset
105
61
  reset_ordered_doubles
106
- reset_double_injections
62
+ Injections::DoubleInjection.reset
107
63
  reset_method_missing_injections
108
64
  reset_singleton_method_added_injections
109
65
  reset_recorded_calls
@@ -111,49 +67,42 @@ module RR
111
67
 
112
68
  # Verifies the DoubleInjection for the passed in subject and method_name.
113
69
  def verify_double(subject, method_name)
114
- @double_injections[subject][method_name].verify
115
- ensure
116
- reset_double subject, method_name
70
+ Injections::DoubleInjection.verify_double(subject, method_name)
117
71
  end
118
72
 
119
73
  # Resets the DoubleInjection for the passed in subject and method_name.
120
74
  def reset_double(subject, method_name)
121
- double_injection = @double_injections[subject].delete(method_name)
122
- @double_injections.delete(subject) if @double_injections[subject].empty?
123
- double_injection.reset
75
+ Injections::DoubleInjection.reset_double(subject, method_name)
124
76
  end
125
-
77
+
126
78
  def record_call(subject, method_name, arguments, block)
127
79
  @recorded_calls << [subject, method_name, arguments, block]
128
80
  end
129
81
 
82
+ def blank_slate_whitelist
83
+ @blank_slate_whitelist ||= [
84
+ "object_id", "respond_to?", "method_missing", "instance_eval", "instance_exec", "class_eval"
85
+ ]
86
+ end
87
+
130
88
  protected
131
89
  # Removes the ordered Doubles from the list
132
90
  def reset_ordered_doubles
133
91
  @ordered_doubles.clear
134
92
  end
135
93
 
136
- # Resets the registered Doubles for the next test run.
137
- def reset_double_injections
138
- @double_injections.each do |subject, method_double_map|
139
- method_double_map.keys.each do |method_name|
140
- reset_double(subject, method_name)
141
- end
142
- end
143
- end
144
-
145
94
  def reset_method_missing_injections
146
- @method_missing_injections.each do |subject, injection|
95
+ Injections::MethodMissingInjection.instances.each do |subject, injection|
147
96
  injection.reset
148
97
  end
149
- @method_missing_injections.clear
98
+ Injections::MethodMissingInjection.instances.clear
150
99
  end
151
100
 
152
101
  def reset_singleton_method_added_injections
153
- @singleton_method_added_injections.each do |subject, injection|
102
+ Injections::SingletonMethodAddedInjection.instances.each do |subject, injection|
154
103
  injection.reset
155
104
  end
156
- @singleton_method_added_injections.clear
105
+ Injections::SingletonMethodAddedInjection.instances.clear
157
106
  end
158
107
 
159
108
  def reset_recorded_calls
@@ -1,11 +1,6 @@
1
1
  module RR
2
2
  class SpyVerificationProxy
3
- instance_methods.each do |m|
4
- unless m =~ /^_/ || m.to_s == 'object_id' || m.to_s == "instance_eval" || m.to_s == "instance_exec" || m.to_s == 'respond_to?'
5
- alias_method "__blank_slated_#{m}", m
6
- undef_method m
7
- end
8
- end
3
+ BlankSlate.call(self)
9
4
 
10
5
  def initialize(subject)
11
6
  @subject = subject
@@ -23,11 +23,9 @@ module RR
23
23
  @strategy_method_name = :mock
24
24
  end
25
25
 
26
- send("normal strategy definition")
27
-
28
26
  context "when passing no args" do
29
- it "returns a DoubleDefinitionCreator" do
30
- call_strategy.class.should == RR::DoubleDefinitions::DoubleDefinitionCreator
27
+ it "returns a DoubleDefinitionCreate" do
28
+ call_strategy.class.should == RR::DoubleDefinitions::DoubleDefinitionCreate
31
29
  end
32
30
  end
33
31
 
@@ -47,11 +45,9 @@ module RR
47
45
  @strategy_method_name = :stub
48
46
  end
49
47
 
50
- send("normal strategy definition")
51
-
52
48
  context "when passing no args" do
53
- it "returns a DoubleDefinitionCreator" do
54
- call_strategy.class.should == RR::DoubleDefinitions::DoubleDefinitionCreator
49
+ it "returns a DoubleDefinitionCreate" do
50
+ call_strategy.class.should == RR::DoubleDefinitions::DoubleDefinitionCreate
55
51
  end
56
52
  end
57
53
 
@@ -70,11 +66,9 @@ module RR
70
66
  @strategy_method_name = :dont_allow
71
67
  end
72
68
 
73
- send("normal strategy definition")
74
-
75
69
  context "when passing no args" do
76
- it "returns a DoubleDefinitionCreator" do
77
- call_strategy.class.should == RR::DoubleDefinitions::DoubleDefinitionCreator
70
+ it "returns a DoubleDefinitionCreate" do
71
+ call_strategy.class.should == RR::DoubleDefinitions::DoubleDefinitionCreate
78
72
  end
79
73
  end
80
74
 
@@ -104,12 +98,10 @@ module RR
104
98
  @strategy_method_name = :mock!
105
99
  end
106
100
 
107
- send("! strategy definition")
108
-
109
101
  context "when passed a method_name argument" do
110
102
  it "sets #verification_strategy to Mock" do
111
103
  proxy = mock!(:foobar)
112
- proxy.double_definition_creator.verification_strategy.class.should == RR::DoubleDefinitions::Strategies::Verification::Mock
104
+ proxy.double_definition_create.verification_strategy.class.should == RR::DoubleDefinitions::Strategies::Verification::Mock
113
105
  end
114
106
  end
115
107
  end
@@ -119,12 +111,10 @@ module RR
119
111
  @strategy_method_name = :stub!
120
112
  end
121
113
 
122
- send("! strategy definition")
123
-
124
114
  context "when passed a method_name argument" do
125
115
  it "sets #verification_strategy to Stub" do
126
116
  proxy = stub!(:foobar)
127
- proxy.double_definition_creator.verification_strategy.class.should == RR::DoubleDefinitions::Strategies::Verification::Stub
117
+ proxy.double_definition_create.verification_strategy.class.should == RR::DoubleDefinitions::Strategies::Verification::Stub
128
118
  end
129
119
  end
130
120
  end
@@ -134,12 +124,10 @@ module RR
134
124
  @strategy_method_name = :dont_allow!
135
125
  end
136
126
 
137
- send("! strategy definition")
138
-
139
127
  context "when passed a method_name argument" do
140
128
  it "sets #verification_strategy to DontAllow" do
141
129
  proxy = dont_allow!(:foobar)
142
- proxy.double_definition_creator.verification_strategy.class.should == RR::DoubleDefinitions::Strategies::Verification::DontAllow
130
+ proxy.double_definition_create.verification_strategy.class.should == RR::DoubleDefinitions::Strategies::Verification::DontAllow
143
131
  end
144
132
  end
145
133
  end