imitate 0.1.6 → 0.2.0
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/.rspec +1 -0
- data/VERSION +1 -1
- data/imitate.gemspec +1 -1
- data/lib/imitate.rb +25 -20
- data/spec/imitate_spec.rb +315 -77
- metadata +3 -3
data/.rspec
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/imitate.gemspec
CHANGED
data/lib/imitate.rb
CHANGED
@@ -23,9 +23,9 @@ module Imitate
|
|
23
23
|
# @param [Proc] Optional block to be instance evaluated on new class.
|
24
24
|
#
|
25
25
|
def mock(name, &block)
|
26
|
-
process_name(name)
|
27
|
-
leaf ?
|
28
|
-
|
26
|
+
process_name(name) do |parent, token, leaf|
|
27
|
+
leaf ? create_class_const(parent, token, &block) : create_module_const(parent, token)
|
28
|
+
end
|
29
29
|
end
|
30
30
|
|
31
31
|
#
|
@@ -35,9 +35,9 @@ module Imitate
|
|
35
35
|
# @param [String] Name of the class to be removed.
|
36
36
|
#
|
37
37
|
def unmock(name)
|
38
|
-
process_name(name)
|
39
|
-
self.send(was_mocked?(parent, token) ? :remove_mock : :get_const, parent, token)
|
40
|
-
|
38
|
+
process_name(name) do |parent, token|
|
39
|
+
self.send((was_mocked?(parent, token) ? :remove_mock : :get_const), parent, token)
|
40
|
+
end
|
41
41
|
end
|
42
42
|
|
43
43
|
#
|
@@ -45,29 +45,28 @@ module Imitate
|
|
45
45
|
# way then using Imitate.
|
46
46
|
#
|
47
47
|
def unmock_all
|
48
|
-
|
49
|
-
remove_mock
|
48
|
+
MOCKED.slice!(0..-1).each do |mock|
|
49
|
+
remove_mock mock[:parent], mock[:name]
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
53
|
private
|
54
54
|
|
55
55
|
def process_name(name)
|
56
|
-
tokens = name.split
|
56
|
+
tokens = name.split '::'
|
57
57
|
parent = Object
|
58
58
|
|
59
|
-
|
60
|
-
|
61
|
-
end
|
59
|
+
tokens[0..-2].each {|token| parent = yield(parent, token, false) }
|
60
|
+
yield parent, tokens[-1], true
|
62
61
|
end
|
63
62
|
|
64
63
|
def was_mocked?(parent, name)
|
65
|
-
MOCKED.index
|
64
|
+
MOCKED.index :parent => parent, :name => name
|
66
65
|
end
|
67
66
|
|
68
67
|
def remove_mock(parent, name)
|
69
|
-
MOCKED.delete
|
70
|
-
remove_const
|
68
|
+
MOCKED.delete :parent => parent, :name => name
|
69
|
+
remove_const parent, name
|
71
70
|
end
|
72
71
|
|
73
72
|
def remove_const(parent, name)
|
@@ -75,20 +74,26 @@ module Imitate
|
|
75
74
|
end
|
76
75
|
|
77
76
|
def get_const(parent, name)
|
78
|
-
parent.const_get
|
77
|
+
parent.const_get name
|
79
78
|
rescue
|
80
79
|
nil
|
81
80
|
end
|
82
81
|
|
83
|
-
def
|
82
|
+
def create_class_const(parent, name, &block)
|
83
|
+
create_const(parent, name) { Class.new(&block) }
|
84
|
+
end
|
85
|
+
|
86
|
+
def create_module_const(parent, name)
|
87
|
+
create_const(parent, name) { Module.new }
|
88
|
+
end
|
89
|
+
|
90
|
+
def create_const(parent, name)
|
84
91
|
begin
|
85
92
|
parent.const_get name
|
86
93
|
rescue
|
87
|
-
clazz_instance = clazz.new(&block)
|
88
|
-
|
89
94
|
MOCKED << {:parent => parent, :name => name}
|
90
95
|
|
91
|
-
parent.const_set name,
|
96
|
+
parent.const_set name, yield
|
92
97
|
end
|
93
98
|
end
|
94
99
|
end
|
data/spec/imitate_spec.rb
CHANGED
@@ -1,134 +1,372 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe Imitate do
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
Imitate.mock('Foo')
|
8
|
-
Imitate.mock('Bar')
|
5
|
+
module FooModule
|
6
|
+
def self.not_an_imitation; end
|
9
7
|
|
10
|
-
|
11
|
-
|
8
|
+
class FooClass; end
|
9
|
+
|
10
|
+
module BarModule
|
11
|
+
class BarClass; end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '.mock' do
|
16
|
+
context 'when const does not exist' do
|
17
|
+
context 'for a simple class' do
|
18
|
+
before { Imitate.mock 'Foo' }
|
19
|
+
|
20
|
+
after { Imitate.unmock 'Foo' }
|
21
|
+
|
22
|
+
it 'should create new dummy class' do
|
23
|
+
Foo.should be
|
24
|
+
Foo.class.should be Class
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'for a class with a block' do
|
29
|
+
before do
|
30
|
+
Imitate.mock('Foo') do
|
31
|
+
def bar
|
32
|
+
'bar'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
after { Imitate.unmock 'Foo' }
|
38
|
+
|
39
|
+
it 'should instance evaluate given block' do
|
40
|
+
Foo.new.should respond_to :bar
|
41
|
+
Foo.new.bar.should == 'bar'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'for a namespaced class' do
|
46
|
+
before { Imitate.mock 'Foo::Bar' }
|
47
|
+
after { Imitate.unmock 'Foo::Bar' }
|
48
|
+
|
49
|
+
it 'should create necessary namespace' do
|
50
|
+
Foo.should be
|
51
|
+
Foo.class.should be Module
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should create namespaced class' do
|
55
|
+
Foo::Bar.should be
|
56
|
+
Foo::Bar.class.should be Class
|
57
|
+
end
|
58
|
+
end
|
12
59
|
|
13
|
-
|
60
|
+
context 'for a deeply namespaced class' do
|
61
|
+
before { Imitate.mock 'Foo::Bar::Baz' }
|
62
|
+
after { Imitate.unmock 'Foo::Bar::Baz' }
|
14
63
|
|
15
|
-
|
16
|
-
|
64
|
+
it 'should create necessary namespace' do
|
65
|
+
Foo.should be
|
66
|
+
Foo.class.should be Module
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should create necessary namespace' do
|
70
|
+
Foo::Bar.should be
|
71
|
+
Foo::Bar.class.should be Module
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should create namespaced class' do
|
75
|
+
Foo::Bar::Baz.should be
|
76
|
+
Foo::Bar::Baz.class.should be Class
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'when const exists' do
|
82
|
+
context 'for a simple class' do
|
83
|
+
before { Imitate.mock 'FooModule' }
|
84
|
+
|
85
|
+
it 'should not override already existing object' do
|
86
|
+
FooModule.class.should be Module
|
87
|
+
FooModule.should respond_to :not_an_imitation
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'for a namespaced class' do
|
92
|
+
before { Imitate.mock 'FooModule::Foo' }
|
93
|
+
after { Imitate.unmock 'FooModule::Foo' }
|
94
|
+
|
95
|
+
it 'should not override already existing object' do
|
96
|
+
FooModule.class.should be Module
|
97
|
+
FooModule.should respond_to :not_an_imitation
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should create namespaced class' do
|
101
|
+
FooModule::Foo.should be
|
102
|
+
FooModule::Foo.class.should be Class
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context 'for a deeply namespaced class' do
|
107
|
+
before { Imitate.mock 'FooModule::Foo::Bar' }
|
108
|
+
after { Imitate.unmock 'FooModule::Foo::Bar' }
|
109
|
+
|
110
|
+
it 'should not override already existing object' do
|
111
|
+
FooModule.class.should be Module
|
112
|
+
FooModule.should respond_to :not_an_imitation
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should create necessary namespace' do
|
116
|
+
FooModule::Foo.should be
|
117
|
+
FooModule::Foo.class.should be Module
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should create namespaced class' do
|
121
|
+
FooModule::Foo::Bar.should be
|
122
|
+
FooModule::Foo::Bar.class.should be Class
|
123
|
+
end
|
124
|
+
end
|
17
125
|
end
|
18
126
|
end
|
19
127
|
|
20
128
|
describe '.unmock' do
|
21
|
-
context '
|
22
|
-
|
23
|
-
|
24
|
-
Imitate.mock('Foo')
|
25
|
-
Imitate.unmock('Foo')
|
129
|
+
context 'when class does not exist' do
|
130
|
+
it 'should do nothing' do
|
131
|
+
Imitate.unmock 'Foo'
|
26
132
|
|
27
|
-
|
28
|
-
|
133
|
+
Imitate.expects(:remove_const).never
|
134
|
+
end
|
135
|
+
end
|
29
136
|
|
30
|
-
|
31
|
-
|
32
|
-
|
137
|
+
context 'without namespaces' do
|
138
|
+
context 'when const was not mocked' do
|
139
|
+
it 'should do nothing' do
|
140
|
+
Imitate.unmock 'FooModule'
|
33
141
|
|
34
|
-
|
35
|
-
lambda { Foo }.should raise_error
|
142
|
+
FooModule.should be
|
36
143
|
end
|
144
|
+
end
|
37
145
|
|
38
|
-
|
39
|
-
|
40
|
-
Imitate.unmock('Foo')
|
146
|
+
context 'when const was mocked' do
|
147
|
+
before { Imitate.mock 'Foo' }
|
41
148
|
|
42
|
-
|
149
|
+
it 'should remove the mocked object' do
|
150
|
+
Imitate.unmock 'Foo'
|
43
151
|
|
44
|
-
|
152
|
+
expect { ::Foo }.to raise_error NameError, 'uninitialized constant Foo'
|
45
153
|
end
|
46
154
|
end
|
155
|
+
end
|
156
|
+
|
157
|
+
context 'with namespaces' do
|
158
|
+
context 'when const was not mocked' do
|
159
|
+
it 'should do nothing' do
|
160
|
+
Imitate.unmock 'FooModule::FooClass'
|
47
161
|
|
48
|
-
|
49
|
-
|
50
|
-
|
162
|
+
FooModule::FooClass.should be
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
context 'when const was mocked' do
|
167
|
+
context 'when no namespace exist' do
|
168
|
+
before { Imitate.mock 'Foo::Bar' }
|
169
|
+
|
170
|
+
it 'should remove the mocked object' do
|
171
|
+
Imitate.unmock 'Foo::Bar'
|
172
|
+
|
173
|
+
expect { ::Foo }.to raise_error NameError, 'uninitialized constant Foo'
|
174
|
+
expect { ::Foo::Bar }.to raise_error NameError, 'uninitialized constant Foo'
|
51
175
|
end
|
52
|
-
|
176
|
+
end
|
53
177
|
|
54
|
-
|
178
|
+
context 'when namespaces already exist' do
|
179
|
+
before { Imitate.mock 'FooModule::Foo' }
|
180
|
+
|
181
|
+
it 'should remove the mocked object' do
|
182
|
+
Imitate.unmock 'FooModule::Foo'
|
55
183
|
|
184
|
+
FooModule.should be
|
185
|
+
expect { ::FooModule::Foo }.to raise_error NameError, 'uninitialized constant FooModule::Foo'
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
context 'with deep namespaces' do
|
192
|
+
context 'when const was not mocked' do
|
56
193
|
it 'should do nothing' do
|
57
|
-
Imitate.unmock
|
194
|
+
Imitate.unmock 'FooModule::BarModule::BarClass'
|
58
195
|
|
59
|
-
|
196
|
+
FooModule::BarModule::BarClass.should be
|
60
197
|
end
|
61
198
|
end
|
62
199
|
|
63
|
-
context '
|
64
|
-
|
65
|
-
|
200
|
+
context 'when const was mocked' do
|
201
|
+
context 'when no namespace exist' do
|
202
|
+
before { Imitate.mock 'Foo::Bar::Baz' }
|
203
|
+
|
204
|
+
it 'should remove the mocked object' do
|
205
|
+
Imitate.unmock 'Foo::Bar::Baz'
|
206
|
+
|
207
|
+
expect { ::Foo }.to raise_error NameError, 'uninitialized constant Foo'
|
208
|
+
expect { ::Foo::Bar }.to raise_error NameError, 'uninitialized constant Foo'
|
209
|
+
expect { ::Foo::Bar::Baz }.to raise_error NameError, 'uninitialized constant Foo'
|
66
210
|
end
|
67
|
-
|
211
|
+
end
|
212
|
+
|
213
|
+
context 'when some namespaces already exist' do
|
214
|
+
before { Imitate.mock 'FooModule::Bar::Baz' }
|
215
|
+
|
216
|
+
it 'should remove the mocked object' do
|
217
|
+
Imitate.unmock_all
|
68
218
|
|
69
|
-
|
219
|
+
FooModule.should be
|
220
|
+
expect { ::FooModule::Bar }.to raise_error NameError, 'uninitialized constant FooModule::Bar'
|
221
|
+
expect { ::FooModule::Bar::Baz }.to raise_error NameError, 'uninitialized constant FooModule::Bar'
|
222
|
+
end
|
223
|
+
end
|
70
224
|
|
71
|
-
|
72
|
-
Imitate.mock
|
73
|
-
|
225
|
+
context 'when all namespaces already exist' do
|
226
|
+
before { Imitate.mock 'FooModule::BarModule::Bar' }
|
227
|
+
|
228
|
+
it 'should remove the mocked object' do
|
229
|
+
Imitate.unmock_all
|
74
230
|
|
75
|
-
|
76
|
-
|
231
|
+
FooModule.should be
|
232
|
+
FooModule::BarModule.should be
|
233
|
+
expect { ::FooModule::BarModule::Bar }.to raise_error NameError, 'uninitialized constant FooModule::BarModule::Bar'
|
234
|
+
end
|
77
235
|
end
|
78
236
|
end
|
79
237
|
end
|
238
|
+
end
|
80
239
|
|
81
|
-
|
82
|
-
|
83
|
-
|
240
|
+
describe '.unmock_all' do
|
241
|
+
context 'without namespaces' do
|
242
|
+
before do
|
243
|
+
Imitate.mock 'Foo'
|
244
|
+
Imitate.mock 'Bar'
|
245
|
+
end
|
84
246
|
|
85
|
-
|
247
|
+
it 'should remove all mocked objects' do
|
248
|
+
Imitate.unmock_all
|
249
|
+
|
250
|
+
expect { ::Foo }.to raise_error NameError, 'uninitialized constant Foo'
|
251
|
+
expect { ::Bar }.to raise_error NameError, 'uninitialized constant Bar'
|
86
252
|
end
|
87
253
|
end
|
88
|
-
end
|
89
254
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
255
|
+
context 'with namespaces' do
|
256
|
+
context 'when namespaces are not the same' do
|
257
|
+
before do
|
258
|
+
Imitate.mock 'Foo::Bar'
|
259
|
+
Imitate.mock 'Baz::Qux'
|
260
|
+
end
|
261
|
+
|
262
|
+
it 'should remove all mocked objects' do
|
263
|
+
Imitate.unmock_all
|
95
264
|
|
96
|
-
|
97
|
-
Foo.
|
98
|
-
|
265
|
+
expect { ::Foo }.to raise_error NameError, 'uninitialized constant Foo'
|
266
|
+
expect { ::Foo::Bar }.to raise_error NameError, 'uninitialized constant Foo'
|
267
|
+
|
268
|
+
expect { ::Baz }.to raise_error NameError, 'uninitialized constant Baz'
|
269
|
+
expect { ::Baz::Qux }.to raise_error NameError, 'uninitialized constant Baz'
|
99
270
|
end
|
100
271
|
end
|
101
272
|
|
102
|
-
context '
|
103
|
-
before
|
104
|
-
Imitate.mock
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
273
|
+
context 'when namespaces are the same' do
|
274
|
+
before do
|
275
|
+
Imitate.mock 'Foo::Bar'
|
276
|
+
Imitate.mock 'Foo::Baz'
|
277
|
+
end
|
278
|
+
|
279
|
+
it 'should remove all mocked objects' do
|
280
|
+
Imitate.unmock_all
|
110
281
|
|
111
|
-
|
112
|
-
Foo.
|
113
|
-
Foo.
|
282
|
+
expect { ::Foo }.to raise_error NameError, 'uninitialized constant Foo'
|
283
|
+
expect { ::Foo::Bar }.to raise_error NameError, 'uninitialized constant Foo'
|
284
|
+
expect { ::Foo::Baz }.to raise_error NameError, 'uninitialized constant Foo'
|
114
285
|
end
|
115
286
|
end
|
116
287
|
|
117
|
-
context '
|
118
|
-
before
|
288
|
+
context 'when namespaces already exist' do
|
289
|
+
before do
|
290
|
+
Imitate.mock 'FooModule::Foo'
|
291
|
+
Imitate.mock 'FooModule::Bar'
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'should remove all mocked objects' do
|
295
|
+
Imitate.unmock_all
|
119
296
|
|
120
|
-
|
121
|
-
Foo
|
122
|
-
|
297
|
+
FooModule.should be
|
298
|
+
expect { ::FooModule::Foo }.to raise_error NameError, 'uninitialized constant FooModule::Foo'
|
299
|
+
expect { ::FooModule::Bar }.to raise_error NameError, 'uninitialized constant FooModule::Bar'
|
123
300
|
end
|
124
301
|
end
|
125
302
|
end
|
126
303
|
|
127
|
-
context '
|
128
|
-
|
304
|
+
context 'with deep namespaces' do
|
305
|
+
context 'when namespaces are not the same' do
|
306
|
+
before do
|
307
|
+
Imitate.mock 'Foo::Bar::Baz'
|
308
|
+
Imitate.mock 'Qux::Quux::Corge'
|
309
|
+
end
|
310
|
+
|
311
|
+
it 'should remove all mocked objects' do
|
312
|
+
Imitate.unmock_all
|
313
|
+
|
314
|
+
expect { ::Foo }.to raise_error NameError, 'uninitialized constant Foo'
|
315
|
+
expect { ::Foo::Bar }.to raise_error NameError, 'uninitialized constant Foo'
|
316
|
+
expect { ::Foo::Bar::Baz }.to raise_error NameError, 'uninitialized constant Foo'
|
129
317
|
|
130
|
-
|
131
|
-
|
318
|
+
expect { ::Qux }.to raise_error NameError, 'uninitialized constant Qux'
|
319
|
+
expect { ::Qux::Quux }.to raise_error NameError, 'uninitialized constant Qux'
|
320
|
+
expect { ::Qux::Quux::Corge }.to raise_error NameError, 'uninitialized constant Qux'
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
context 'when namespaces are the same' do
|
325
|
+
before do
|
326
|
+
Imitate.mock 'Foo::Bar::Baz'
|
327
|
+
Imitate.mock 'Foo::Bar::Qux'
|
328
|
+
end
|
329
|
+
|
330
|
+
it 'should remove all mocked objects' do
|
331
|
+
Imitate.unmock_all
|
332
|
+
|
333
|
+
expect { ::Foo }.to raise_error NameError, 'uninitialized constant Foo'
|
334
|
+
expect { ::Foo::Bar }.to raise_error NameError, 'uninitialized constant Foo'
|
335
|
+
expect { ::Foo::Bar::Baz }.to raise_error NameError, 'uninitialized constant Foo'
|
336
|
+
expect { ::Foo::Bar::Qux }.to raise_error NameError, 'uninitialized constant Foo'
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
context 'when namespaces already exist' do
|
341
|
+
before do
|
342
|
+
Imitate.mock 'FooModule::Bar::Baz'
|
343
|
+
Imitate.mock 'FooModule::Bar::Qux'
|
344
|
+
end
|
345
|
+
|
346
|
+
it 'should remove all mocked objects' do
|
347
|
+
Imitate.unmock_all
|
348
|
+
|
349
|
+
FooModule.should be
|
350
|
+
expect { ::FooModule::Bar }.to raise_error NameError, 'uninitialized constant FooModule::Bar'
|
351
|
+
expect { ::FooModule::Bar::Baz }.to raise_error NameError, 'uninitialized constant FooModule::Bar'
|
352
|
+
expect { ::FooModule::Bar::Qux }.to raise_error NameError, 'uninitialized constant FooModule::Bar'
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
context 'when all namespaces already exist' do
|
357
|
+
before do
|
358
|
+
Imitate.mock 'FooModule::BarModule::Bar'
|
359
|
+
Imitate.mock 'FooModule::BarModule::Baz'
|
360
|
+
end
|
361
|
+
|
362
|
+
it 'should remove all mocked objects' do
|
363
|
+
Imitate.unmock_all
|
364
|
+
|
365
|
+
FooModule.should be
|
366
|
+
FooModule::BarModule.should be
|
367
|
+
expect { ::FooModule::BarModule::Bar }.to raise_error NameError, 'uninitialized constant FooModule::BarModule::Bar'
|
368
|
+
expect { ::FooModule::BarModule::Baz }.to raise_error NameError, 'uninitialized constant FooModule::BarModule::Baz'
|
369
|
+
end
|
132
370
|
end
|
133
371
|
end
|
134
372
|
end
|