rr 0.1.5 → 0.1.6
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 +3 -0
- data/README +7 -0
- data/Rakefile +1 -1
- data/examples/rr/probe_creator_example.rb +12 -0
- data/examples/rr/scenario_example.rb +34 -0
- data/lib/rr/probe_creator.rb +17 -6
- data/lib/rr/scenario.rb +39 -15
- metadata +2 -2
data/CHANGES
CHANGED
data/README
CHANGED
@@ -25,6 +25,13 @@ renders the partial.
|
|
25
25
|
|
26
26
|
view = controller.template
|
27
27
|
probe(view).render(:partial => "user_info")
|
28
|
+
|
29
|
+
Probes also support after_call callbacks. This is useful for Stubbing out
|
30
|
+
a class method and getting its return value. For example, using ActiveRecord:
|
31
|
+
|
32
|
+
probe(User).find('5') do |user|
|
33
|
+
mock(user).valid? {false}
|
34
|
+
end
|
28
35
|
|
29
36
|
== Block Syntax
|
30
37
|
script = MyScript.new
|
data/Rakefile
CHANGED
@@ -78,6 +78,18 @@ describe ProbeCreator, "#method_missing" do
|
|
78
78
|
@subject.foobar(1, 2).should == :baz
|
79
79
|
proc {@subject.foobar(1, 2)}.should raise_error(Errors::TimesCalledError)
|
80
80
|
end
|
81
|
+
|
82
|
+
it "sets after_call on the scenario when passed a block" do
|
83
|
+
real_value = Object.new
|
84
|
+
(class << @subject; self; end).class_eval do
|
85
|
+
define_method(:foobar) {real_value}
|
86
|
+
end
|
87
|
+
@creator.foobar(1, 2) {|value| mock(value).a_method {99}}
|
88
|
+
|
89
|
+
return_value = @subject.foobar(1, 2)
|
90
|
+
return_value.should === return_value
|
91
|
+
return_value.a_method.should == 99
|
92
|
+
end
|
81
93
|
end
|
82
94
|
|
83
95
|
end
|
@@ -195,6 +195,40 @@ describe Scenario, "#yields" do
|
|
195
195
|
end
|
196
196
|
end
|
197
197
|
|
198
|
+
describe Scenario, "#after_call" do
|
199
|
+
it_should_behave_like "RR::Scenario"
|
200
|
+
|
201
|
+
it "returns self" do
|
202
|
+
@scenario.after_call {}.should === @scenario
|
203
|
+
end
|
204
|
+
|
205
|
+
it "receives the return value in the block" do
|
206
|
+
return_value = {}
|
207
|
+
@scenario.returns(return_value).after_call do |value|
|
208
|
+
value[:foo] = :bar
|
209
|
+
end
|
210
|
+
|
211
|
+
actual_value = @scenario.call
|
212
|
+
actual_value.should === return_value
|
213
|
+
actual_value.should == {:foo => :bar}
|
214
|
+
end
|
215
|
+
|
216
|
+
it "allows after_call to mock the return value" do
|
217
|
+
return_value = Object.new
|
218
|
+
@scenario.with_any_args.returns(return_value).after_call do |value|
|
219
|
+
mock(value).inner_method(1) {:baz}
|
220
|
+
end
|
221
|
+
|
222
|
+
@object.foobar.inner_method(1).should == :baz
|
223
|
+
end
|
224
|
+
|
225
|
+
it "raises an error when not passed a block" do
|
226
|
+
proc do
|
227
|
+
@scenario.after_call
|
228
|
+
end.should raise_error(ArgumentError, "after_call expects a block")
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
198
232
|
describe Scenario, "#returns" do
|
199
233
|
it_should_behave_like "RR::Scenario"
|
200
234
|
|
data/lib/rr/probe_creator.rb
CHANGED
@@ -3,15 +3,24 @@ module RR
|
|
3
3
|
# a Scenario that acts like a probe.
|
4
4
|
#
|
5
5
|
# The following example probes method_name with arg1 and arg2
|
6
|
-
# returning
|
6
|
+
# returning the actual value of the method. The block is an after callback
|
7
|
+
# that intercepts the return value. Mocks or other modifications can
|
8
|
+
# be done to the return value.
|
7
9
|
#
|
8
|
-
# probe(subject).method_name(arg1, arg2) { return_value }
|
10
|
+
# probe(subject).method_name(arg1, arg2) { |return_value| }
|
9
11
|
#
|
10
|
-
# The ProbeCreator also supports a block sytnax.
|
12
|
+
# The ProbeCreator also supports a block sytnax. The block accepts
|
13
|
+
# a after_call callback, instead of a return value as with MockCreator
|
14
|
+
# and StubCreator.
|
11
15
|
#
|
12
|
-
# probe(
|
13
|
-
# m.
|
16
|
+
# probe(User) do |m|
|
17
|
+
# m.find('4') do |user|
|
18
|
+
# mock(user).valid? {false}
|
19
|
+
# end
|
14
20
|
# end
|
21
|
+
#
|
22
|
+
# user = User.find('4')
|
23
|
+
# user.valid? # false
|
15
24
|
class ProbeCreator
|
16
25
|
instance_methods.each { |m| undef_method m unless m =~ /^__/ }
|
17
26
|
|
@@ -22,10 +31,12 @@ module RR
|
|
22
31
|
end
|
23
32
|
|
24
33
|
protected
|
25
|
-
def method_missing(method_name, *args, &
|
34
|
+
def method_missing(method_name, *args, &after_call)
|
26
35
|
double = @space.create_double(@subject, method_name)
|
27
36
|
scenario = @space.create_scenario(double)
|
28
37
|
scenario.with(*args).once.implemented_by(double.original_method)
|
38
|
+
scenario.after_call(&after_call) if after_call
|
39
|
+
scenario
|
29
40
|
end
|
30
41
|
end
|
31
42
|
end
|
data/lib/rr/scenario.rb
CHANGED
@@ -11,6 +11,7 @@ module RR
|
|
11
11
|
@argument_expectation = nil
|
12
12
|
@times_called_expectation = nil
|
13
13
|
@times_called = 0
|
14
|
+
@after_call = nil
|
14
15
|
@yields = nil
|
15
16
|
end
|
16
17
|
|
@@ -114,6 +115,37 @@ module RR
|
|
114
115
|
@ordered
|
115
116
|
end
|
116
117
|
|
118
|
+
# Scenario#yields sets the Scenario to invoke a passed in block when
|
119
|
+
# the Scenario is called.
|
120
|
+
# An Expection will be raised if no block is passed in when the
|
121
|
+
# Scenario is called.
|
122
|
+
#
|
123
|
+
# Passing in a block sets the return value.
|
124
|
+
#
|
125
|
+
# mock(subject).method_name.yields(yield_arg1, yield_arg2) {return_value}
|
126
|
+
# subject.method_name {|yield_arg1, yield_arg2|}
|
127
|
+
def yields(*args, &returns)
|
128
|
+
@yields = args
|
129
|
+
returns(&returns) if returns
|
130
|
+
self
|
131
|
+
end
|
132
|
+
|
133
|
+
# Scenario#after_call creates a callback that occurs after call
|
134
|
+
# is called. The passed in block receives the return value of
|
135
|
+
# the Scenario being called.
|
136
|
+
# An Expection will be raised if no block is passed in.
|
137
|
+
#
|
138
|
+
# mock(subject).method_name {return_value}.after_call {|return_value|}
|
139
|
+
# subject.method_name # return_value
|
140
|
+
#
|
141
|
+
# This feature is built into probes.
|
142
|
+
# probe(User).find('1') {|user| mock(user).valid? {false}}
|
143
|
+
def after_call(&block)
|
144
|
+
raise ArgumentError, "after_call expects a block" unless block
|
145
|
+
@after_call = block
|
146
|
+
self
|
147
|
+
end
|
148
|
+
|
117
149
|
# Scenario#returns accepts an argument value or a block.
|
118
150
|
# It will raise an ArgumentError if both are passed in.
|
119
151
|
#
|
@@ -130,21 +162,6 @@ module RR
|
|
130
162
|
end
|
131
163
|
end
|
132
164
|
|
133
|
-
# Scenario#yields sets the Scenario to invoke a passed in block when
|
134
|
-
# the Scenario is called.
|
135
|
-
# An Expection will be raised if no block is passed in when the
|
136
|
-
# Scenario is called.
|
137
|
-
#
|
138
|
-
# Passing in a block sets the return value.
|
139
|
-
#
|
140
|
-
# mock(subject).method_name.yields(yield_arg1, yield_arg2) {return_value}
|
141
|
-
# subject.method_name {|yield_arg1, yield_arg2|}
|
142
|
-
def yields(*args, &returns)
|
143
|
-
@yields = args
|
144
|
-
returns(&returns) if returns
|
145
|
-
self
|
146
|
-
end
|
147
|
-
|
148
165
|
# Scenario#implemented_by sets the implementation of the Scenario.
|
149
166
|
# This method takes a Proc or a Method. Passing in a Method allows
|
150
167
|
# the Scenario to accept blocks.
|
@@ -165,6 +182,12 @@ module RR
|
|
165
182
|
# A TimesCalledError is raised when the times called
|
166
183
|
# exceeds the expected TimesCalledExpectation.
|
167
184
|
def call(*args, &block)
|
185
|
+
return_value = call_implementation(*args, &block)
|
186
|
+
@after_call.call(return_value) if @after_call
|
187
|
+
return_value
|
188
|
+
end
|
189
|
+
|
190
|
+
def call_implementation(*args, &block)
|
168
191
|
@times_called_expectation.verify_input if @times_called_expectation
|
169
192
|
@space.verify_ordered_scenario(self) if ordered?
|
170
193
|
if @yields
|
@@ -182,6 +205,7 @@ module RR
|
|
182
205
|
return @implementation.call(*args)
|
183
206
|
end
|
184
207
|
end
|
208
|
+
protected :call_implementation
|
185
209
|
|
186
210
|
# Scenario#exact_match? returns true when the passed in arguments
|
187
211
|
# exactly match the ArgumentEqualityError arguments.
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.3
|
|
3
3
|
specification_version: 1
|
4
4
|
name: rr
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.1.
|
7
|
-
date: 2007-07-
|
6
|
+
version: 0.1.6
|
7
|
+
date: 2007-07-10 00:00:00 -07:00
|
8
8
|
summary: RR (Double Ruby) is a double framework that features a rich selection of double techniques and a terse syntax. http://xunitpatterns.com/Test%20Double.html
|
9
9
|
require_paths:
|
10
10
|
- lib
|