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 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