jferris-rr 0.7.1.0.1239654108
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/CHANGES +196 -0
- data/README.rdoc +329 -0
- data/Rakefile +77 -0
- data/lib/rr.rb +84 -0
- data/lib/rr/adapters/rr_methods.rb +122 -0
- data/lib/rr/adapters/rspec.rb +58 -0
- data/lib/rr/adapters/test_unit.rb +29 -0
- data/lib/rr/double.rb +212 -0
- data/lib/rr/double_definitions/child_double_definition_creator.rb +27 -0
- data/lib/rr/double_definitions/double_definition.rb +346 -0
- data/lib/rr/double_definitions/double_definition_creator.rb +167 -0
- data/lib/rr/double_definitions/double_definition_creator_proxy.rb +37 -0
- data/lib/rr/double_definitions/strategies/implementation/implementation_strategy.rb +15 -0
- data/lib/rr/double_definitions/strategies/implementation/proxy.rb +62 -0
- data/lib/rr/double_definitions/strategies/implementation/reimplementation.rb +14 -0
- data/lib/rr/double_definitions/strategies/implementation/strongly_typed_reimplementation.rb +17 -0
- data/lib/rr/double_definitions/strategies/scope/instance.rb +15 -0
- data/lib/rr/double_definitions/strategies/scope/instance_of_class.rb +46 -0
- data/lib/rr/double_definitions/strategies/scope/scope_strategy.rb +15 -0
- data/lib/rr/double_definitions/strategies/strategy.rb +70 -0
- data/lib/rr/double_definitions/strategies/verification/dont_allow.rb +34 -0
- data/lib/rr/double_definitions/strategies/verification/mock.rb +44 -0
- data/lib/rr/double_definitions/strategies/verification/stub.rb +45 -0
- data/lib/rr/double_definitions/strategies/verification/verification_strategy.rb +15 -0
- data/lib/rr/double_injection.rb +143 -0
- data/lib/rr/double_matches.rb +51 -0
- data/lib/rr/errors/argument_equality_error.rb +6 -0
- data/lib/rr/errors/double_definition_error.rb +6 -0
- data/lib/rr/errors/double_not_found_error.rb +6 -0
- data/lib/rr/errors/double_order_error.rb +6 -0
- data/lib/rr/errors/rr_error.rb +20 -0
- data/lib/rr/errors/spy_verification_errors/double_injection_not_found_error.rb +8 -0
- data/lib/rr/errors/spy_verification_errors/invocation_count_error.rb +8 -0
- data/lib/rr/errors/spy_verification_errors/spy_verification_error.rb +8 -0
- data/lib/rr/errors/subject_does_not_implement_method_error.rb +6 -0
- data/lib/rr/errors/subject_has_different_arity_error.rb +6 -0
- data/lib/rr/errors/times_called_error.rb +6 -0
- data/lib/rr/expectations/any_argument_expectation.rb +21 -0
- data/lib/rr/expectations/argument_equality_expectation.rb +41 -0
- data/lib/rr/expectations/times_called_expectation.rb +57 -0
- data/lib/rr/hash_with_object_id_key.rb +41 -0
- data/lib/rr/recorded_calls.rb +103 -0
- data/lib/rr/space.rb +123 -0
- data/lib/rr/spy_verification.rb +48 -0
- data/lib/rr/spy_verification_proxy.rb +18 -0
- data/lib/rr/times_called_matchers/any_times_matcher.rb +18 -0
- data/lib/rr/times_called_matchers/at_least_matcher.rb +15 -0
- data/lib/rr/times_called_matchers/at_most_matcher.rb +23 -0
- data/lib/rr/times_called_matchers/integer_matcher.rb +19 -0
- data/lib/rr/times_called_matchers/non_terminal.rb +27 -0
- data/lib/rr/times_called_matchers/proc_matcher.rb +11 -0
- data/lib/rr/times_called_matchers/range_matcher.rb +21 -0
- data/lib/rr/times_called_matchers/terminal.rb +20 -0
- data/lib/rr/times_called_matchers/times_called_matcher.rb +44 -0
- data/lib/rr/wildcard_matchers/anything.rb +18 -0
- data/lib/rr/wildcard_matchers/boolean.rb +23 -0
- data/lib/rr/wildcard_matchers/duck_type.rb +32 -0
- data/lib/rr/wildcard_matchers/hash_including.rb +29 -0
- data/lib/rr/wildcard_matchers/is_a.rb +25 -0
- data/lib/rr/wildcard_matchers/numeric.rb +13 -0
- data/lib/rr/wildcard_matchers/range.rb +7 -0
- data/lib/rr/wildcard_matchers/regexp.rb +7 -0
- data/lib/rr/wildcard_matchers/satisfy.rb +26 -0
- data/spec/core_spec_suite.rb +19 -0
- data/spec/environment_fixture_setup.rb +6 -0
- data/spec/high_level_spec.rb +368 -0
- data/spec/rr/adapters/rr_methods_argument_matcher_spec.rb +67 -0
- data/spec/rr/adapters/rr_methods_creator_spec.rb +149 -0
- data/spec/rr/adapters/rr_methods_space_spec.rb +115 -0
- data/spec/rr/adapters/rr_methods_spec_helper.rb +11 -0
- data/spec/rr/adapters/rr_methods_times_matcher_spec.rb +17 -0
- data/spec/rr/double_definitions/child_double_definition_creator_spec.rb +112 -0
- data/spec/rr/double_definitions/double_definition_creator_proxy_spec.rb +155 -0
- data/spec/rr/double_definitions/double_definition_creator_spec.rb +502 -0
- data/spec/rr/double_definitions/double_definition_spec.rb +1159 -0
- data/spec/rr/double_injection/double_injection_bind_spec.rb +111 -0
- data/spec/rr/double_injection/double_injection_dispatching_spec.rb +244 -0
- data/spec/rr/double_injection/double_injection_has_original_method_spec.rb +55 -0
- data/spec/rr/double_injection/double_injection_reset_spec.rb +90 -0
- data/spec/rr/double_injection/double_injection_spec.rb +77 -0
- data/spec/rr/double_injection/double_injection_verify_spec.rb +29 -0
- data/spec/rr/double_spec.rb +352 -0
- data/spec/rr/errors/rr_error_spec.rb +67 -0
- data/spec/rr/expectations/any_argument_expectation_spec.rb +47 -0
- data/spec/rr/expectations/anything_argument_equality_expectation_spec.rb +14 -0
- data/spec/rr/expectations/argument_equality_expectation_spec.rb +135 -0
- data/spec/rr/expectations/boolean_argument_equality_expectation_spec.rb +34 -0
- data/spec/rr/expectations/hash_including_argument_equality_expectation_spec.rb +82 -0
- data/spec/rr/expectations/hash_including_spec.rb +17 -0
- data/spec/rr/expectations/satisfy_argument_equality_expectation_spec.rb +59 -0
- data/spec/rr/expectations/satisfy_spec.rb +14 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_any_times_spec.rb +46 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_least_spec.rb +69 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_most_spec.rb +71 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_helper.rb +23 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_integer_spec.rb +104 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_proc_spec.rb +81 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_range_spec.rb +83 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_spec.rb +38 -0
- data/spec/rr/rspec/invocation_matcher_spec.rb +279 -0
- data/spec/rr/rspec/rspec_adapter_spec.rb +66 -0
- data/spec/rr/rspec/rspec_backtrace_tweaking_spec.rb +31 -0
- data/spec/rr/rspec/rspec_backtrace_tweaking_spec_fixture.rb +11 -0
- data/spec/rr/rspec/rspec_usage_spec.rb +86 -0
- data/spec/rr/space/hash_with_object_id_key_spec.rb +88 -0
- data/spec/rr/space/space_spec.rb +542 -0
- data/spec/rr/test_unit/test_helper.rb +7 -0
- data/spec/rr/test_unit/test_unit_backtrace_test.rb +35 -0
- data/spec/rr/test_unit/test_unit_integration_test.rb +57 -0
- data/spec/rr/times_called_matchers/any_times_matcher_spec.rb +47 -0
- data/spec/rr/times_called_matchers/at_least_matcher_spec.rb +55 -0
- data/spec/rr/times_called_matchers/at_most_matcher_spec.rb +70 -0
- data/spec/rr/times_called_matchers/integer_matcher_spec.rb +70 -0
- data/spec/rr/times_called_matchers/proc_matcher_spec.rb +55 -0
- data/spec/rr/times_called_matchers/range_matcher_spec.rb +76 -0
- data/spec/rr/times_called_matchers/times_called_matcher_spec.rb +118 -0
- data/spec/rr/wildcard_matchers/anything_spec.rb +24 -0
- data/spec/rr/wildcard_matchers/boolean_spec.rb +36 -0
- data/spec/rr/wildcard_matchers/duck_type_spec.rb +52 -0
- data/spec/rr/wildcard_matchers/is_a_spec.rb +32 -0
- data/spec/rr/wildcard_matchers/numeric_spec.rb +32 -0
- data/spec/rr/wildcard_matchers/range_spec.rb +35 -0
- data/spec/rr/wildcard_matchers/regexp_spec.rb +43 -0
- data/spec/rr_spec.rb +28 -0
- data/spec/rspec_spec_suite.rb +16 -0
- data/spec/spec_helper.rb +107 -0
- data/spec/spec_suite.rb +27 -0
- data/spec/spy_verification_spec.rb +129 -0
- data/spec/test_unit_spec_suite.rb +21 -0
- metadata +187 -0
|
@@ -0,0 +1,143 @@
|
|
|
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
|
+
MethodArguments = Struct.new(:arguments, :block)
|
|
8
|
+
attr_reader :subject, :method_name, :doubles
|
|
9
|
+
|
|
10
|
+
def initialize(subject, method_name)
|
|
11
|
+
@subject = subject
|
|
12
|
+
@method_name = method_name.to_sym
|
|
13
|
+
if object_has_method?(method_name)
|
|
14
|
+
begin
|
|
15
|
+
meta.__send__(:alias_method, original_method_name, method_name)
|
|
16
|
+
rescue NameError => e
|
|
17
|
+
subject.send(method_name)
|
|
18
|
+
meta.__send__(:alias_method, original_method_name, method_name)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
@doubles = []
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# RR::DoubleInjection#register_double adds the passed in Double
|
|
25
|
+
# into this DoubleInjection's list of Double objects.
|
|
26
|
+
def register_double(double)
|
|
27
|
+
@doubles << double
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# RR::DoubleInjection#bind injects a method that acts as a dispatcher
|
|
31
|
+
# that dispatches to the matching Double when the method
|
|
32
|
+
# is called.
|
|
33
|
+
def bind
|
|
34
|
+
define_implementation_placeholder
|
|
35
|
+
returns_method = <<-METHOD
|
|
36
|
+
def #{@method_name}(*args, &block)
|
|
37
|
+
arguments = MethodArguments.new(args, block)
|
|
38
|
+
__send__('#{placeholder_name}', arguments)
|
|
39
|
+
end
|
|
40
|
+
METHOD
|
|
41
|
+
meta.class_eval(returns_method, __FILE__, __LINE__ - 5)
|
|
42
|
+
self
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# RR::DoubleInjection#verify verifies each Double
|
|
46
|
+
# TimesCalledExpectation are met.
|
|
47
|
+
def verify
|
|
48
|
+
@doubles.each do |double|
|
|
49
|
+
double.verify
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# RR::DoubleInjection#reset removes the injected dispatcher method.
|
|
54
|
+
# It binds the original method implementation on the subject
|
|
55
|
+
# if one exists.
|
|
56
|
+
def reset
|
|
57
|
+
meta.__send__(:remove_method, placeholder_name)
|
|
58
|
+
if object_has_original_method?
|
|
59
|
+
meta.__send__(:alias_method, @method_name, original_method_name)
|
|
60
|
+
meta.__send__(:remove_method, original_method_name)
|
|
61
|
+
else
|
|
62
|
+
meta.__send__(:remove_method, @method_name)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def call_original_method(*args, &block)
|
|
67
|
+
@subject.__send__(original_method_name, *args, &block)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def object_has_original_method?
|
|
71
|
+
object_has_method?(original_method_name)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
protected
|
|
75
|
+
def define_implementation_placeholder
|
|
76
|
+
me = self
|
|
77
|
+
meta.__send__(:define_method, placeholder_name) do |arguments|
|
|
78
|
+
me.__send__(:call_method, arguments.arguments, arguments.block)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def call_method(args, block)
|
|
83
|
+
space.record_call(subject, method_name, args, block)
|
|
84
|
+
if double = find_double_to_attempt(args)
|
|
85
|
+
double.call(self, *args, &block)
|
|
86
|
+
else
|
|
87
|
+
double_not_found_error(*args)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def find_double_to_attempt(args)
|
|
92
|
+
matches = DoubleMatches.new(@doubles).find_all_matches(args)
|
|
93
|
+
|
|
94
|
+
unless matches.exact_terminal_doubles_to_attempt.empty?
|
|
95
|
+
return matches.exact_terminal_doubles_to_attempt.first
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
unless matches.exact_non_terminal_doubles_to_attempt.empty?
|
|
99
|
+
return matches.exact_non_terminal_doubles_to_attempt.last
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
unless matches.wildcard_terminal_doubles_to_attempt.empty?
|
|
103
|
+
return matches.wildcard_terminal_doubles_to_attempt.first
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
unless matches.wildcard_non_terminal_doubles_to_attempt.empty?
|
|
107
|
+
return matches.wildcard_non_terminal_doubles_to_attempt.last
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
unless matches.matching_doubles.empty?
|
|
111
|
+
return matches.matching_doubles.first # This will raise a TimesCalledError
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
return nil
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def double_not_found_error(*args)
|
|
118
|
+
message =
|
|
119
|
+
"On subject #{subject},\n" <<
|
|
120
|
+
"unexpected method invocation:\n" <<
|
|
121
|
+
" #{Double.formatted_name(@method_name, args)}\n" <<
|
|
122
|
+
"expected invocations:\n" <<
|
|
123
|
+
Double.list_message_part(@doubles)
|
|
124
|
+
raise Errors::DoubleNotFoundError, message
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def placeholder_name
|
|
128
|
+
"__rr__#{@method_name}"
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def original_method_name
|
|
132
|
+
"__rr__original_#{@method_name}"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def object_has_method?(method_name)
|
|
136
|
+
@subject.methods.include?(method_name.to_s) || @subject.respond_to?(method_name)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def meta
|
|
140
|
+
(class << @subject; self; end)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module RR
|
|
2
|
+
class DoubleMatches
|
|
3
|
+
attr_reader :matching_doubles,
|
|
4
|
+
:exact_terminal_doubles_to_attempt,
|
|
5
|
+
:exact_non_terminal_doubles_to_attempt,
|
|
6
|
+
:wildcard_terminal_doubles_to_attempt,
|
|
7
|
+
:wildcard_non_terminal_doubles_to_attempt
|
|
8
|
+
def initialize(doubles) #:nodoc:
|
|
9
|
+
@doubles = doubles
|
|
10
|
+
@matching_doubles = []
|
|
11
|
+
@exact_terminal_doubles_to_attempt = []
|
|
12
|
+
@exact_non_terminal_doubles_to_attempt = []
|
|
13
|
+
@wildcard_terminal_doubles_to_attempt = []
|
|
14
|
+
@wildcard_non_terminal_doubles_to_attempt = []
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def find_all_matches(args)
|
|
18
|
+
@doubles.each do |double|
|
|
19
|
+
if double.exact_match?(*args)
|
|
20
|
+
matching_doubles << double
|
|
21
|
+
if double.attempt?
|
|
22
|
+
exact_double_is_terminal_or_non_terminal double
|
|
23
|
+
end
|
|
24
|
+
elsif double.wildcard_match?(*args)
|
|
25
|
+
matching_doubles << double
|
|
26
|
+
if double.attempt?
|
|
27
|
+
wildcard_double_is_terminal_or_non_terminal double
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
self
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
protected
|
|
35
|
+
def exact_double_is_terminal_or_non_terminal(double)
|
|
36
|
+
if double.terminal?
|
|
37
|
+
exact_terminal_doubles_to_attempt << double
|
|
38
|
+
else
|
|
39
|
+
exact_non_terminal_doubles_to_attempt << double
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def wildcard_double_is_terminal_or_non_terminal(double)
|
|
44
|
+
if double.terminal?
|
|
45
|
+
wildcard_terminal_doubles_to_attempt << double
|
|
46
|
+
else
|
|
47
|
+
wildcard_non_terminal_doubles_to_attempt << double
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module RR
|
|
2
|
+
module Errors
|
|
3
|
+
BACKTRACE_IDENTIFIER = Regexp.new("/lib/rr")
|
|
4
|
+
|
|
5
|
+
class RRError < RuntimeError
|
|
6
|
+
attr_writer :backtrace
|
|
7
|
+
def backtrace
|
|
8
|
+
original_backtrace = (@backtrace) ? @backtrace : super
|
|
9
|
+
return original_backtrace unless RR.trim_backtrace
|
|
10
|
+
|
|
11
|
+
return original_backtrace unless original_backtrace.respond_to?(:each)
|
|
12
|
+
new_backtrace = []
|
|
13
|
+
original_backtrace.each do |line|
|
|
14
|
+
new_backtrace << line unless line =~ BACKTRACE_IDENTIFIER
|
|
15
|
+
end
|
|
16
|
+
new_backtrace
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module RR
|
|
2
|
+
module Expectations
|
|
3
|
+
class AnyArgumentExpectation < ArgumentEqualityExpectation #:nodoc:
|
|
4
|
+
def initialize
|
|
5
|
+
super
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def exact_match?(*arguments)
|
|
9
|
+
false
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def wildcard_match?(*arguments)
|
|
13
|
+
true
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def ==(other)
|
|
17
|
+
other.is_a?(self.class)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module RR
|
|
2
|
+
module Expectations
|
|
3
|
+
class ArgumentEqualityExpectation #:nodoc:
|
|
4
|
+
attr_reader :expected_arguments
|
|
5
|
+
|
|
6
|
+
def initialize(*expected_arguments)
|
|
7
|
+
@expected_arguments = expected_arguments
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def exact_match?(*arguments)
|
|
11
|
+
return false unless arguments.length == expected_arguments.length
|
|
12
|
+
arguments.each_with_index do |arg, index|
|
|
13
|
+
return false unless equality_match(expected_arguments[index], arg)
|
|
14
|
+
end
|
|
15
|
+
true
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def wildcard_match?(*arguments)
|
|
19
|
+
return false unless arguments.length == expected_arguments.length
|
|
20
|
+
arguments.each_with_index do |arg, index|
|
|
21
|
+
expected_argument = expected_arguments[index]
|
|
22
|
+
if expected_argument.respond_to?(:wildcard_match?)
|
|
23
|
+
return false unless expected_argument.wildcard_match?(arg)
|
|
24
|
+
else
|
|
25
|
+
return false unless equality_match(expected_argument, arg)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
true
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def ==(other)
|
|
32
|
+
expected_arguments == other.expected_arguments
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
protected
|
|
36
|
+
def equality_match(arg1, arg2)
|
|
37
|
+
arg1.respond_to?(:'__rr__original_==') ? arg1.__send__(:'__rr__original_==', arg2) : arg1 == arg2
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module RR
|
|
2
|
+
module Expectations
|
|
3
|
+
class TimesCalledExpectation #:nodoc:
|
|
4
|
+
attr_reader :double, :times_called
|
|
5
|
+
|
|
6
|
+
def initialize(double)
|
|
7
|
+
@double = double
|
|
8
|
+
@times_called = 0
|
|
9
|
+
@verify_backtrace = caller[1..-1]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def attempt?
|
|
13
|
+
times_matcher.attempt?(@times_called)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def attempt
|
|
17
|
+
@times_called += 1
|
|
18
|
+
verify_input_error unless times_matcher.possible_match?(@times_called)
|
|
19
|
+
return
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def verify
|
|
23
|
+
return false unless times_matcher.is_a?(TimesCalledMatchers::TimesCalledMatcher)
|
|
24
|
+
return times_matcher.matches?(@times_called)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def verify!
|
|
28
|
+
unless verify
|
|
29
|
+
if @verify_backtrace
|
|
30
|
+
error = Errors::TimesCalledError.new(error_message)
|
|
31
|
+
error.backtrace = @verify_backtrace
|
|
32
|
+
raise error
|
|
33
|
+
else
|
|
34
|
+
raise Errors::TimesCalledError, error_message
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def terminal?
|
|
40
|
+
times_matcher.terminal?
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
protected
|
|
44
|
+
def times_matcher
|
|
45
|
+
double.definition.times_matcher
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def verify_input_error
|
|
49
|
+
raise Errors::TimesCalledError, error_message
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def error_message
|
|
53
|
+
"#{double.formatted_name}\n#{times_matcher.error_message(@times_called)}"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module RR
|
|
2
|
+
class HashWithObjectIdKey < ::Hash #:nodoc:
|
|
3
|
+
def initialize
|
|
4
|
+
@keys = {}
|
|
5
|
+
super do |hash, subject_object|
|
|
6
|
+
hash.set_with_object_id(subject_object, {})
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
alias_method :get_with_object_id, :[]
|
|
11
|
+
def [](key)
|
|
12
|
+
@keys[key.__id__] = key
|
|
13
|
+
super(key.__id__)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
alias_method :set_with_object_id, :[]=
|
|
17
|
+
def []=(key, value)
|
|
18
|
+
@keys[key.__id__] = key
|
|
19
|
+
super(key.__id__, value)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def each
|
|
23
|
+
super do |object_id, value|
|
|
24
|
+
yield @keys[object_id], value
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def delete(key)
|
|
29
|
+
@keys.delete(key.__id__)
|
|
30
|
+
super(key.__id__)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def keys
|
|
34
|
+
@keys.values
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def include?(key)
|
|
38
|
+
super(key.__id__)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|