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 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
 
@@ -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
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :minor: 10
3
- :patch: 0
3
+ :patch: 2
4
4
  :major: 0
@@ -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
- implemented_by implementation
252
+ install_method_callback implementation
254
253
  else
255
- implemented_by proc {value}
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
- returns(&block)
292
+ implemented_by block
292
293
  end
293
294
  end
294
295
  end
@@ -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 object_has_method?(method_name)
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
- object_has_method?(original_method_alias_name)
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 object_has_method?(method_name)
119
- @subject.methods.include?(method_name.to_s) || @subject.respond_to?(method_name)
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
- it "overrides the original method with the double_injection's dispatching methods" do
24
- double_injection.bind
25
- subject.method(:foobar).should_not == original_method
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
- it "stores original method in __rr__original_method_alias_name" do
29
- subject.respond_to?(:__rr__original_foobar).should == true
30
- subject.method(:__rr__original_foobar).should == original_method
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
- double = new_double(anything) {:return_value}
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
- double_1 = new_double(anything) {:value_1}
111
- double_2 = new_double(anything) {:value_2}
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
- exact_double_registered_first = new_double(1, 2) {:exact_first}
118
- wildcard_double_registered_last = new_double(anything, anything) {:wildcard_last}
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
- double1_with_exact_match = new_double(:exact_match) {:return_1}
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
- double1_with_exact_match = new_double(:exact_match) {:return_1}
140
- double2_with_exact_match = new_double(:exact_match) {:return_2}
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
- double1_with_exact_match = new_double(:exact_match) {:return_1}
148
- double2_with_exact_match = new_double(:exact_match) {:return_2}
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
- double1_with_exact_match = new_double(:exact_match) {:return_1}
156
- double2_with_exact_match = new_double(:exact_match) {:return_2}
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
- double_1 = new_double {:return_1}
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
- double_1 = new_double {:return_1}
182
- double_2 = new_double {:return_2}
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
- double_1 = new_double {:return_1}
190
- double_2 = new_double {:return_2}
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
- double_1 = new_double {:return_1}
198
- double_2 = new_double {:return_2}
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 "and invoking the method for the first time does not add the method" do
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 does not have original method" do
50
- double_injection.object_has_original_method?.should be_false
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.0
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-06-01 00:00:00 -07:00
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.1
186
+ rubygems_version: 1.3.5
185
187
  signing_key:
186
- specification_version: 2
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