rr 0.10.0 → 0.10.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +7 -0
- data/README.rdoc +8 -0
- data/Rakefile +35 -0
- data/VERSION.yml +1 -1
- data/lib/rr/double_definitions/double_definition.rb +5 -4
- data/lib/rr/double_injection.rb +18 -4
- data/spec/rr/double_injection/double_injection_bind_spec.rb +34 -8
- data/spec/rr/double_injection/double_injection_dispatching_spec.rb +19 -19
- data/spec/rr/double_injection/double_injection_spec.rb +21 -5
- metadata +6 -4
data/CHANGES
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
0.10.2
|
2
|
+
- RR properly proxies subjects with private methods [http://github.com/btakita/rr/issues/#issue/7]. Identified by Matthew O'Connor.
|
3
|
+
|
4
|
+
0.10.1
|
5
|
+
- Fixed issue with DoubleInjection not invoking methods that are lazily created [http://github.com/btakita/rr/issues/#issue/4]. Identified by davidlee (http://github.com/davidlee)
|
6
|
+
- Fixed issue with mock.proxy and returns [http://github.com/btakita/rr/issues/#issue/2]. Identified by trogdoro (http://github.com/trogdoro)
|
7
|
+
|
1
8
|
* 0.10.0
|
2
9
|
- Method is no longer invoked if respond_to? returns false. This was in place to support ActiveRecord association proxies, and is no longer needed.
|
3
10
|
|
data/README.rdoc
CHANGED
@@ -38,6 +38,14 @@ Currently RR implements mocks, stubs, proxies, and spies. Fakes usually require
|
|
38
38
|
# config.mock_with RR::Adapters::Rspec
|
39
39
|
end
|
40
40
|
|
41
|
+
== standalone
|
42
|
+
extend RR::Adapters::RRMethods
|
43
|
+
mock(object).method_name {:return_value}
|
44
|
+
|
45
|
+
object.method_name # Returns :return_value
|
46
|
+
|
47
|
+
RR.verify # Verifies the Double expectations are satisfied
|
48
|
+
|
41
49
|
== Syntax between RR and other double/mock frameworks
|
42
50
|
=== Terse Syntax
|
43
51
|
One of the goals of RR is to make doubles more scannable.
|
data/Rakefile
CHANGED
@@ -47,3 +47,38 @@ begin
|
|
47
47
|
rescue LoadError
|
48
48
|
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
49
49
|
end
|
50
|
+
RUBYFORGE_PACKAGE_NAME = "rr (Double R)"
|
51
|
+
|
52
|
+
# This is hacked to get around the 3 character limitation for package names on Rubyforge.
|
53
|
+
# http://rubyforge.org/tracker/index.php?func=detail&aid=27026&group_id=5&atid=102
|
54
|
+
class Jeweler
|
55
|
+
module Commands
|
56
|
+
class ReleaseToRubyforge
|
57
|
+
def run
|
58
|
+
raise NoRubyForgeProjectInGemspecError unless @gemspec.rubyforge_project
|
59
|
+
|
60
|
+
@rubyforge.configure rescue nil
|
61
|
+
|
62
|
+
output.puts 'Logging in rubyforge'
|
63
|
+
@rubyforge.login
|
64
|
+
|
65
|
+
@rubyforge.userconfig['release_notes'] = @gemspec.description if @gemspec.description
|
66
|
+
@rubyforge.userconfig['preformatted'] = true
|
67
|
+
|
68
|
+
output.puts "Releasing #{@gemspec.name}-#{@version} to #{@gemspec.rubyforge_project}"
|
69
|
+
begin
|
70
|
+
@rubyforge.add_release(@gemspec.rubyforge_project, RUBYFORGE_PACKAGE_NAME, @version.to_s, @gemspec_helper.gem_path)
|
71
|
+
rescue StandardError => e
|
72
|
+
case e.message
|
73
|
+
when /no <group_id> configured for <#{Regexp.escape @gemspec.rubyforge_project}>/
|
74
|
+
raise RubyForgeProjectNotConfiguredError, @gemspec.rubyforge_project
|
75
|
+
when /no <package_id> configured for <#{Regexp.escape @gemspec.name}>/i
|
76
|
+
raise MissingRubyForgePackageError, @gemspec.name
|
77
|
+
else
|
78
|
+
raise
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/VERSION.yml
CHANGED
@@ -245,14 +245,15 @@ module RR
|
|
245
245
|
#
|
246
246
|
# Passing in an argument causes Double to return the argument.
|
247
247
|
def returns(*args, &implementation)
|
248
|
-
value = args.first
|
249
248
|
if !args.empty? && implementation
|
250
249
|
raise ArgumentError, "returns cannot accept both an argument and a block"
|
251
250
|
end
|
252
251
|
if implementation
|
253
|
-
|
252
|
+
install_method_callback implementation
|
254
253
|
else
|
255
|
-
|
254
|
+
install_method_callback(lambda do
|
255
|
+
return *args
|
256
|
+
end)
|
256
257
|
end
|
257
258
|
self
|
258
259
|
end
|
@@ -288,7 +289,7 @@ module RR
|
|
288
289
|
if implementation_is_original_method?
|
289
290
|
after_call(&block)
|
290
291
|
else
|
291
|
-
|
292
|
+
implemented_by block
|
292
293
|
end
|
293
294
|
end
|
294
295
|
end
|
data/lib/rr/double_injection.rb
CHANGED
@@ -4,6 +4,13 @@ module RR
|
|
4
4
|
# has Argument Expectations and Times called Expectations.
|
5
5
|
class DoubleInjection
|
6
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
|
+
|
7
14
|
MethodArguments = Struct.new(:arguments, :block)
|
8
15
|
attr_reader :subject, :method_name, :doubles, :subject_class
|
9
16
|
|
@@ -11,7 +18,10 @@ module RR
|
|
11
18
|
@subject = subject
|
12
19
|
@subject_class = subject_class
|
13
20
|
@method_name = method_name.to_sym
|
14
|
-
if
|
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
|
15
25
|
subject_class.__send__(:alias_method, original_method_alias_name, method_name)
|
16
26
|
end
|
17
27
|
@doubles = []
|
@@ -62,7 +72,7 @@ module RR
|
|
62
72
|
end
|
63
73
|
|
64
74
|
def object_has_original_method?
|
65
|
-
|
75
|
+
subject_respond_to_method?(original_method_alias_name)
|
66
76
|
end
|
67
77
|
|
68
78
|
def call_method(args, block)
|
@@ -115,8 +125,12 @@ module RR
|
|
115
125
|
"__rr__original_#{@method_name}"
|
116
126
|
end
|
117
127
|
|
118
|
-
def
|
119
|
-
|
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)
|
120
134
|
end
|
121
135
|
end
|
122
136
|
end
|
@@ -16,18 +16,44 @@ module RR
|
|
16
16
|
@subject.methods.should include(method_name.to_s)
|
17
17
|
|
18
18
|
subject.method(:foobar).should == original_method
|
19
|
-
|
20
|
-
@double_injection = RR::Space.double_injection(subject, method_name)
|
21
19
|
end
|
22
20
|
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
26
38
|
end
|
27
39
|
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
31
57
|
end
|
32
58
|
end
|
33
59
|
|
@@ -102,20 +102,20 @@ module RR
|
|
102
102
|
end
|
103
103
|
|
104
104
|
it "dispatches to Double with wildcard match" do
|
105
|
-
|
105
|
+
new_double(anything) {:return_value}
|
106
106
|
subject.foobar(:dont_care).should == :return_value
|
107
107
|
end
|
108
108
|
|
109
109
|
it "matches to the last Double that was registered with a wildcard match" do
|
110
|
-
|
111
|
-
|
110
|
+
new_double(anything) {:value_1}
|
111
|
+
new_double(anything) {:value_2}
|
112
112
|
|
113
113
|
subject.foobar(:dont_care).should == :value_2
|
114
114
|
end
|
115
115
|
|
116
116
|
it "matches to Double with exact match Double even when a Double with wildcard match was registered later" do
|
117
|
-
|
118
|
-
|
117
|
+
new_double(1, 2) {:exact_first}
|
118
|
+
new_double(anything, anything) {:wildcard_last}
|
119
119
|
|
120
120
|
subject.foobar(1, 2).should == :exact_first
|
121
121
|
end
|
@@ -130,30 +130,30 @@ module RR
|
|
130
130
|
|
131
131
|
context "when two or more Terminal Doubles with duplicate Exact Match ArgumentExpectations exists" do
|
132
132
|
it "dispatches to Double that have an exact match" do
|
133
|
-
|
133
|
+
new_double(:exact_match) {:return_1}
|
134
134
|
|
135
135
|
subject.foobar(:exact_match).should == :return_1
|
136
136
|
end
|
137
137
|
|
138
138
|
it "dispatches to the first Double that have an exact match" do
|
139
|
-
|
140
|
-
|
139
|
+
new_double(:exact_match) {:return_1}
|
140
|
+
new_double(:exact_match) {:return_2}
|
141
141
|
|
142
142
|
subject.foobar(:exact_match).should == :return_1
|
143
143
|
end
|
144
144
|
|
145
145
|
it "dispatches the second Double with an exact match
|
146
146
|
when the first double's Times Called expectation is satisfied" do
|
147
|
-
|
148
|
-
|
147
|
+
new_double(:exact_match) {:return_1}
|
148
|
+
new_double(:exact_match) {:return_2}
|
149
149
|
|
150
150
|
subject.foobar(:exact_match)
|
151
151
|
subject.foobar(:exact_match).should == :return_2
|
152
152
|
end
|
153
153
|
|
154
154
|
it "raises TimesCalledError when all of the doubles Times Called expectation is satisfied" do
|
155
|
-
|
156
|
-
|
155
|
+
new_double(:exact_match) {:return_1}
|
156
|
+
new_double(:exact_match) {:return_2}
|
157
157
|
|
158
158
|
subject.foobar(:exact_match)
|
159
159
|
subject.foobar(:exact_match)
|
@@ -172,30 +172,30 @@ module RR
|
|
172
172
|
|
173
173
|
context "when two or more Doubles with duplicate Wildcard Match ArgumentExpectations exists" do
|
174
174
|
it "dispatches to Double that have a wildcard match" do
|
175
|
-
|
175
|
+
new_double {:return_1}
|
176
176
|
|
177
177
|
subject.foobar(:anything).should == :return_1
|
178
178
|
end
|
179
179
|
|
180
180
|
it "dispatches to the first Double that has a wildcard match" do
|
181
|
-
|
182
|
-
|
181
|
+
new_double {:return_1}
|
182
|
+
new_double {:return_2}
|
183
183
|
|
184
184
|
subject.foobar(:anything).should == :return_1
|
185
185
|
end
|
186
186
|
|
187
187
|
it "dispatches the second Double with a wildcard match
|
188
188
|
when the first double's Times Called expectation is satisfied" do
|
189
|
-
|
190
|
-
|
189
|
+
new_double {:return_1}
|
190
|
+
new_double {:return_2}
|
191
191
|
|
192
192
|
subject.foobar(:anything)
|
193
193
|
subject.foobar(:anything).should == :return_2
|
194
194
|
end
|
195
195
|
|
196
196
|
it "raises TimesCalledError when all of the doubles Times Called expectation is satisfied" do
|
197
|
-
|
198
|
-
|
197
|
+
new_double {:return_1}
|
198
|
+
new_double {:return_2}
|
199
199
|
|
200
200
|
subject.foobar(:anything)
|
201
201
|
subject.foobar(:anything)
|
@@ -23,14 +23,14 @@ module RR
|
|
23
23
|
end
|
24
24
|
|
25
25
|
context "when method_name is a string" do
|
26
|
-
send("sets up object and method_name")
|
27
|
-
|
28
26
|
before do
|
29
27
|
@subject = Object.new
|
30
28
|
@method_name = 'foobar'
|
31
29
|
subject.methods.should_not include(method_name)
|
32
30
|
@double_injection = DoubleInjection.new(subject, method_name, (class << subject; self; end))
|
33
31
|
end
|
32
|
+
|
33
|
+
send("sets up object and method_name")
|
34
34
|
end
|
35
35
|
|
36
36
|
context "when method does not exist on object" do
|
@@ -40,14 +40,30 @@ module RR
|
|
40
40
|
subject.methods.should_not include(method_name.to_s)
|
41
41
|
end
|
42
42
|
|
43
|
-
context "
|
43
|
+
context "when the subject descends from active record" do
|
44
44
|
before do
|
45
|
+
def subject.descends_from_active_record?
|
46
|
+
true
|
47
|
+
end
|
48
|
+
def subject.respond_to?(name)
|
49
|
+
return true if name == :foobar
|
50
|
+
super
|
51
|
+
end
|
52
|
+
def subject.method_missing(name, *args, &block)
|
53
|
+
if name == :foobar
|
54
|
+
def self.foobar
|
55
|
+
end
|
56
|
+
else
|
57
|
+
super
|
58
|
+
end
|
59
|
+
end
|
45
60
|
@double_injection = DoubleInjection.new(subject, method_name, (class << subject; self; end))
|
46
61
|
end
|
62
|
+
|
47
63
|
send("sets up object and method_name")
|
48
64
|
|
49
|
-
example "object
|
50
|
-
double_injection.object_has_original_method?.should
|
65
|
+
example "object has the original method" do
|
66
|
+
double_injection.object_has_original_method?.should be_true
|
51
67
|
end
|
52
68
|
end
|
53
69
|
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.
|
4
|
+
version: 0.10.2
|
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-
|
12
|
+
date: 2009-08-30 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -158,6 +158,8 @@ files:
|
|
158
158
|
- spec/test_unit_spec_suite.rb
|
159
159
|
has_rdoc: true
|
160
160
|
homepage: http://pivotallabs.com
|
161
|
+
licenses: []
|
162
|
+
|
161
163
|
post_install_message:
|
162
164
|
rdoc_options:
|
163
165
|
- --main
|
@@ -181,9 +183,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
181
183
|
requirements: []
|
182
184
|
|
183
185
|
rubyforge_project: pivotalrb
|
184
|
-
rubygems_version: 1.3.
|
186
|
+
rubygems_version: 1.3.5
|
185
187
|
signing_key:
|
186
|
-
specification_version:
|
188
|
+
specification_version: 3
|
187
189
|
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
|
188
190
|
test_files:
|
189
191
|
- spec/spy_verification_spec.rb
|