rr 0.10.0 → 0.10.2
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 +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
|