imitate 0.1.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec CHANGED
@@ -1 +1,2 @@
1
1
  --color
2
+ --format documentation
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.6
1
+ 0.2.0
data/imitate.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "imitate"
8
- s.version = "0.1.6"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Petr Janda", "Pericles Dias"]
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) {|parent, token, leaf|
27
- leaf ? create_const(Class, parent, token, &block) : create_const(Module, parent, token)
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) {|parent, token|
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
- while mock = MOCKED.shift
49
- remove_mock(mock[:parent], mock[:name])
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
- while token = tokens.shift
60
- parent = yield(parent, token, tokens.length == 0)
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({:parent => parent, :name => name})
64
+ MOCKED.index :parent => parent, :name => name
66
65
  end
67
66
 
68
67
  def remove_mock(parent, name)
69
- MOCKED.delete({:parent => parent, :name => name})
70
- remove_const(parent, name)
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(name)
77
+ parent.const_get name
79
78
  rescue
80
79
  nil
81
80
  end
82
81
 
83
- def create_const(clazz, parent, name, &block)
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, clazz_instance
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 "Imitate" do
3
+ describe Imitate do
4
4
 
5
- describe '.unmock_all' do
6
- it 'should remove all mocked objects' do
7
- Imitate.mock('Foo')
8
- Imitate.mock('Bar')
5
+ module FooModule
6
+ def self.not_an_imitation; end
9
7
 
10
- Foo.should be
11
- Bar.should be
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
- Imitate.unmock_all
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
- lambda { Foo }.should raise_error
16
- lambda { Bar }.should raise_error
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 'const exists' do
22
- context 'const was mocked by imitate' do
23
- it 'should remove the class' do
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
- lambda { Object.const_get('Foo') }.should raise_error
28
- end
133
+ Imitate.expects(:remove_const).never
134
+ end
135
+ end
29
136
 
30
- it 'should remove the class and namespaces' do
31
- Imitate.mock('Foo::Bar')
32
- Imitate.unmock('Foo::Bar')
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
- lambda { Foo::Bar }.should raise_error
35
- lambda { Foo }.should raise_error
142
+ FooModule.should be
36
143
  end
144
+ end
37
145
 
38
- it 'should remove record from MOCKED' do
39
- Imitate.mock('Foo')
40
- Imitate.unmock('Foo')
146
+ context 'when const was mocked' do
147
+ before { Imitate.mock 'Foo' }
41
148
 
42
- Imitate.expects(:remove_const).never
149
+ it 'should remove the mocked object' do
150
+ Imitate.unmock 'Foo'
43
151
 
44
- Imitate.unmock('Foo')
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
- context 'if const was not mocked' do
49
- before {
50
- class Foo1
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
- after { Object.instance_eval { remove_const 'Foo1' } }
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('Foo1')
194
+ Imitate.unmock 'FooModule::BarModule::BarClass'
58
195
 
59
- Foo1.should be
196
+ FooModule::BarModule::BarClass.should be
60
197
  end
61
198
  end
62
199
 
63
- context 'if class was not mocked in existing module' do
64
- before {
65
- module Module1
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
- after { Object.instance_eval { remove_const 'Module1' } }
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
- it 'should remove just class' do
72
- Imitate.mock('Module1::Foo1')
73
- Imitate.unmock('Module1::Foo1')
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
- Module1.should be
76
- lambda { Module1::Foo1 }.should raise_error
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
- context 'class doesnt exist' do
82
- it 'should do nothing' do
83
- Imitate.unmock('Foo1')
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
- Imitate.expects(:remove_const).never
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
- describe '.mock' do
91
- context 'if const doesnt exist' do
92
- context 'simple class' do
93
- before { Imitate.mock('Foo') }
94
- after { Imitate.unmock('Foo') }
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
- it 'should create new dummy class' do
97
- Foo.should be
98
- Foo.class.should == Class
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 'class with block' do
103
- before {
104
- Imitate.mock('Foo') do
105
- def bar
106
- 'bar'
107
- end
108
- end
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
- it 'should instance evaluate given block' do
112
- Foo.new.methods.map(&:to_s).should include 'bar'
113
- Foo.new.bar.should == 'bar'
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 'class within namespace' do
118
- before { Imitate.mock('Foo::Bar') }
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
- it 'should create necessary namespace' do
121
- Foo::Bar.should be
122
- Foo::Bar.class.should == Class
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 'if const exists' do
128
- before { Imitate.mock('Imitate') }
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
- it 'should not override already existing object' do
131
- Imitate.methods.map(&:to_s).should include 'mock'
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
metadata CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 1
9
- - 6
10
- version: 0.1.6
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Petr Janda