soveran-override 0.0.6 → 0.0.7
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/README.markdown +3 -2
- data/lib/override.rb +1 -60
- data/test/all_test.rb +59 -20
- metadata +1 -1
data/README.markdown
CHANGED
@@ -49,7 +49,7 @@ It is a common pattern to set expectations for method calls. You can do
|
|
49
49
|
it with the `expect` function:
|
50
50
|
|
51
51
|
user = User.spawn :name => "Foobar"
|
52
|
-
expect(User, :find, :
|
52
|
+
expect(User, :find, :with => [:first, { :include => :friendships }], :return => user)
|
53
53
|
|
54
54
|
And then:
|
55
55
|
|
@@ -68,7 +68,8 @@ of calls received by the redefined method. The RSpec equivalent of
|
|
68
68
|
triggers an exception if the method is not called. While it is a handy
|
69
69
|
feature, it encourages coupling and testing internals, so my advice
|
70
70
|
would be to use it scarcely and to try to refactor your code so it
|
71
|
-
doesn't follow this testing anti-pattern.
|
71
|
+
doesn't follow this testing anti-pattern. Check the tests for more
|
72
|
+
examples.
|
72
73
|
|
73
74
|
Installation
|
74
75
|
------------
|
data/lib/override.rb
CHANGED
@@ -1,60 +1,3 @@
|
|
1
|
-
# Override
|
2
|
-
#
|
3
|
-
# This is the pure esence of the stubbing concept: it takes an object,
|
4
|
-
# a hash of methods/results, and proceeds to rewrite each method in the
|
5
|
-
# object. It can be used as a stubbing strategy in most cases, and I'd
|
6
|
-
# say that cases that don't fit this pattern have a very bad code smell,
|
7
|
-
# because are either dealing with internals or with side effects.
|
8
|
-
#
|
9
|
-
# Usage
|
10
|
-
#
|
11
|
-
# require 'override'
|
12
|
-
#
|
13
|
-
# @user = User.spawn
|
14
|
-
# override(@user, :name => "Foobar", :email => "foobar@example.org")
|
15
|
-
# override(User, :find => @user)
|
16
|
-
#
|
17
|
-
# Or alternatively:
|
18
|
-
#
|
19
|
-
# override(User, :find => override(User.spawn, :name => "Foobar, :email => "foobar@example.org"))
|
20
|
-
#
|
21
|
-
# In case you don't know what spawn means, check my other library for
|
22
|
-
# testing at http://github.com/soveran/spawner.
|
23
|
-
#
|
24
|
-
# Note: the arity strictness in Ruby 1.9 demands for that trick that
|
25
|
-
# drops the arguments passed to the redefined method. It's not necessary
|
26
|
-
# in Ruby 1.8.
|
27
|
-
#
|
28
|
-
# You can also send lambdas that will become the body of the redefined method:
|
29
|
-
#
|
30
|
-
# user = User.spawn :name => "Foobar"
|
31
|
-
# override(User, :find => lambda { |id| raise ArgumentError unless id == 1; user })
|
32
|
-
#
|
33
|
-
# And then, in your tests:
|
34
|
-
#
|
35
|
-
# assert_raise ArgumentError do
|
36
|
-
# User.find(2)
|
37
|
-
# end
|
38
|
-
#
|
39
|
-
# assert_nothing_raised do
|
40
|
-
# User.find(1)
|
41
|
-
# end
|
42
|
-
#
|
43
|
-
# assert_equal "Foobar", User.find(1).name
|
44
|
-
#
|
45
|
-
# It is a common pattern to set expectations for method calls. You can
|
46
|
-
# do it with the expect function:
|
47
|
-
#
|
48
|
-
# user = User.spawn :name => "Foobar"
|
49
|
-
# expect(User, :find, :return => user, :params => [:first, { :include => :friendships }])
|
50
|
-
#
|
51
|
-
# And then:
|
52
|
-
#
|
53
|
-
# assert_equal "Foobar", User.find(:first, :include => :friendships).name
|
54
|
-
# assert_raise ArgumentError do
|
55
|
-
# User.find(:all)
|
56
|
-
# end
|
57
|
-
#
|
58
1
|
require "rubygems"
|
59
2
|
require "metaid"
|
60
3
|
|
@@ -64,15 +7,13 @@ def override object, methods
|
|
64
7
|
object.meta_def(method, &result.to_proc) :
|
65
8
|
object.meta_def(method) { |*_| result }
|
66
9
|
end
|
67
|
-
|
68
10
|
object
|
69
11
|
end
|
70
12
|
|
71
13
|
def expect object, method, options
|
72
14
|
expectation = lambda do |*params|
|
73
|
-
raise ArgumentError unless params == options[:
|
15
|
+
raise ArgumentError unless params == options[:with]
|
74
16
|
options[:return]
|
75
17
|
end
|
76
|
-
|
77
18
|
override(object, method => expectation)
|
78
19
|
end
|
data/test/all_test.rb
CHANGED
@@ -17,11 +17,22 @@ class Foo
|
|
17
17
|
"Qux"
|
18
18
|
end
|
19
19
|
|
20
|
+
def nom
|
21
|
+
Bar.foo(1, 2, 3)
|
22
|
+
true
|
23
|
+
end
|
24
|
+
|
20
25
|
def == other
|
21
26
|
bar == other.bar
|
22
27
|
end
|
23
28
|
end
|
24
29
|
|
30
|
+
class Bar
|
31
|
+
def self.foo(a, b, c)
|
32
|
+
"Bar/Foo"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
25
36
|
class Callable
|
26
37
|
def to_proc
|
27
38
|
lambda do |name|
|
@@ -37,11 +48,11 @@ class TestOverride < Test::Unit::TestCase
|
|
37
48
|
override(@foo, :bar => "Hello")
|
38
49
|
end
|
39
50
|
|
40
|
-
|
51
|
+
should "work without arguments" do
|
41
52
|
assert_equal "Hello", @foo.bar
|
42
53
|
end
|
43
54
|
|
44
|
-
|
55
|
+
should "discard arguments" do
|
45
56
|
assert_equal "Hello", @foo.bar(1)
|
46
57
|
end
|
47
58
|
end
|
@@ -52,17 +63,17 @@ class TestOverride < Test::Unit::TestCase
|
|
52
63
|
@foo2 = Foo.new
|
53
64
|
end
|
54
65
|
|
55
|
-
|
66
|
+
should "work for string returns" do
|
56
67
|
override(@foo, :bar => "Hello")
|
57
68
|
assert_equal "Hello", @foo.bar
|
58
69
|
end
|
59
70
|
|
60
|
-
|
71
|
+
should "work for numeric returns" do
|
61
72
|
override(@foo, :bar => 23)
|
62
73
|
assert_equal 23, @foo.bar
|
63
74
|
end
|
64
75
|
|
65
|
-
|
76
|
+
should "work for object returns" do
|
66
77
|
override(@foo, :bar => @foo2)
|
67
78
|
assert_equal @foo2, @foo.bar
|
68
79
|
end
|
@@ -73,19 +84,19 @@ class TestOverride < Test::Unit::TestCase
|
|
73
84
|
@foo = Foo.new
|
74
85
|
end
|
75
86
|
|
76
|
-
|
87
|
+
should "work for methods that used to receive blocks" do
|
77
88
|
override(@foo, :baz => "Hey!")
|
78
89
|
assert_equal "Hey!", @foo.baz { |x| x }
|
79
90
|
end
|
80
91
|
|
81
|
-
|
92
|
+
should "work for methods that used to receive arguments" do
|
82
93
|
override(@foo, :qux => "Yay!")
|
83
94
|
assert_equal "Yay!", @foo.qux(1, 2, 3)
|
84
95
|
end
|
85
96
|
end
|
86
97
|
|
87
98
|
context "rewriting multiple methods at once" do
|
88
|
-
|
99
|
+
should "override all the passed methods" do
|
89
100
|
override(@foo, :bar => 1, :baz => 2, :qux => 3)
|
90
101
|
assert_equal 1, @foo.bar
|
91
102
|
assert_equal 2, @foo.baz
|
@@ -94,13 +105,13 @@ class TestOverride < Test::Unit::TestCase
|
|
94
105
|
end
|
95
106
|
|
96
107
|
context "chaining successive calls" do
|
97
|
-
|
108
|
+
should "return the object and allow chained calls" do
|
98
109
|
assert_equal 1, override(@foo, :bar => 1).bar
|
99
110
|
end
|
100
111
|
end
|
101
112
|
|
102
113
|
context "dealing with a proc as the result value" do
|
103
|
-
|
114
|
+
should "uses the proc as the body of the method" do
|
104
115
|
override(@foo, :bar => lambda { |name| "Hello #{name}" })
|
105
116
|
assert_equal "Hello World", @foo.bar("World")
|
106
117
|
end
|
@@ -118,7 +129,7 @@ class TestOverride < Test::Unit::TestCase
|
|
118
129
|
override(@foo, :bar => lambda { |id| raise ArgumentError unless id == 1; user })
|
119
130
|
end
|
120
131
|
|
121
|
-
|
132
|
+
should "lambdas should be able to raise exceptions" do
|
122
133
|
assert_raise ArgumentError do
|
123
134
|
@foo.bar(2)
|
124
135
|
end
|
@@ -139,11 +150,11 @@ class TestOverride < Test::Unit::TestCase
|
|
139
150
|
override(@foo, :baz => lambda { @name })
|
140
151
|
end
|
141
152
|
|
142
|
-
|
153
|
+
should "succeeds when the lambda returns a local variable" do
|
143
154
|
assert_equal "Michel", @foo.bar
|
144
155
|
end
|
145
156
|
|
146
|
-
|
157
|
+
should "fails when the lambda is supposed to return an instance variable" do
|
147
158
|
assert_equal nil, @foo.baz
|
148
159
|
end
|
149
160
|
end
|
@@ -153,7 +164,7 @@ class TestOverride < Test::Unit::TestCase
|
|
153
164
|
override(@foo, :bar => Callable.new)
|
154
165
|
end
|
155
166
|
|
156
|
-
|
167
|
+
should "coerces the value into a proc" do
|
157
168
|
assert_equal "Hello World", @foo.bar("World")
|
158
169
|
end
|
159
170
|
end
|
@@ -163,23 +174,23 @@ class TestOverride < Test::Unit::TestCase
|
|
163
174
|
override(@foo, :bar => lambda { lambda { "Hey!" } })
|
164
175
|
end
|
165
176
|
|
166
|
-
|
177
|
+
should "returns a lambda if it's wraped inside a proc" do
|
167
178
|
assert_equal "Hey!", @foo.bar.call
|
168
179
|
end
|
169
180
|
end
|
170
181
|
|
171
182
|
context "setting expectations" do
|
172
183
|
setup do
|
173
|
-
expect(@foo, :bar, :
|
184
|
+
expect(@foo, :bar, :with => ["Michel", 32], :return => true)
|
174
185
|
end
|
175
186
|
|
176
|
-
|
187
|
+
should "raises an error if expectations are not met" do
|
177
188
|
assert_raise ArgumentError do
|
178
189
|
@foo.bar "Michel", 31
|
179
190
|
end
|
180
191
|
end
|
181
192
|
|
182
|
-
|
193
|
+
should "succeeds if expectations are met" do
|
183
194
|
assert_nothing_raised do
|
184
195
|
@foo.bar "Michel", 32
|
185
196
|
end
|
@@ -188,13 +199,41 @@ class TestOverride < Test::Unit::TestCase
|
|
188
199
|
|
189
200
|
context "setting expectations with hashes in the param list" do
|
190
201
|
setup do
|
191
|
-
expect(@foo, :bar, :
|
202
|
+
expect(@foo, :bar, :with => ["Michel", { :include => :friendships, :select => "name" }], :return => true)
|
192
203
|
end
|
193
204
|
|
194
|
-
|
205
|
+
should "succeeds if expectations are met" do
|
195
206
|
assert_nothing_raised do
|
196
207
|
@foo.bar "Michel", { :select => "name", :include => :friendships, :select => "name" }
|
197
208
|
end
|
198
209
|
end
|
199
210
|
end
|
211
|
+
|
212
|
+
context "side effects" do
|
213
|
+
setup do
|
214
|
+
@foo = Foo.new
|
215
|
+
expect(Bar, :foo, :with => [1, 2, 3], :return => "Bar/Bar")
|
216
|
+
end
|
217
|
+
|
218
|
+
should "don't affect the interface" do
|
219
|
+
assert_equal true, @foo.nom
|
220
|
+
end
|
221
|
+
|
222
|
+
should "detect the method call as a side effect" do
|
223
|
+
override(Bar, :foo => lambda { |*_| raise ArgumentError })
|
224
|
+
assert_raise ArgumentError do
|
225
|
+
@foo.nom
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
should "don't affect the interfaces!" do
|
230
|
+
@foo = Foo.new
|
231
|
+
expect(Bar, :foo, :with => [1, 2, 3], :return => "Bar/Bar")
|
232
|
+
assert_equal true, @foo.nom
|
233
|
+
override(Bar, :foo => lambda { |*_| raise ArgumentError })
|
234
|
+
assert_raise ArgumentError do
|
235
|
+
@foo.nom
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
200
239
|
end
|