gabrielg-factory_girl 1.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,591 @@
1
+ require(File.join(File.dirname(__FILE__), 'test_helper'))
2
+
3
+ class FactoryTest < Test::Unit::TestCase
4
+
5
+ def self.should_instantiate_class
6
+
7
+ should "instantiate the build class" do
8
+ assert_kind_of @class, @instance
9
+ end
10
+
11
+ should "assign attributes on the instance" do
12
+ assert_equal @first_name, @instance.first_name
13
+ assert_equal @last_name, @instance.last_name
14
+ end
15
+
16
+ should "override attributes using the passed hash" do
17
+ @value = 'Davis'
18
+ @instance = @factory.build(:first_name => @value)
19
+ assert_equal @value, @instance.first_name
20
+ end
21
+
22
+ end
23
+
24
+ context "defining a factory" do
25
+
26
+ setup do
27
+ @name = :user
28
+ @factory = mock('factory')
29
+ @factory.stubs(:factory_name).returns(@name)
30
+ @options = { :class => 'magic' }
31
+ Factory.stubs(:new).returns(@factory)
32
+ end
33
+
34
+ should "create a new factory using the specified name and options" do
35
+ Factory.expects(:new).with(@name, @options).returns(@factory)
36
+ Factory.define(@name, @options) {|f| }
37
+ end
38
+
39
+ should "pass the factory do the block" do
40
+ yielded = nil
41
+ Factory.define(@name) do |y|
42
+ yielded = y
43
+ end
44
+ assert_equal @factory, yielded
45
+ end
46
+
47
+ should "add the factory to the list of factories" do
48
+ Factory.define(@name) {|f| }
49
+ assert_equal Factory.factories[@name],
50
+ @factory,
51
+ "Factories: #{Factory.factories.inspect}"
52
+ end
53
+
54
+ end
55
+
56
+ context "a factory" do
57
+
58
+ setup do
59
+ @name = :user
60
+ @class = User
61
+ @factory = Factory.new(@name)
62
+ end
63
+
64
+ should "have a factory name" do
65
+ assert_equal @name, @factory.factory_name
66
+ end
67
+
68
+ should "have a build class" do
69
+ assert_equal @class, @factory.build_class
70
+ end
71
+
72
+ should "have a set of callbacks" do
73
+ assert @factory.instance_eval {@callbacks}
74
+ end
75
+
76
+ should "have an empty set of callbacks when none have been set" do
77
+ assert @factory.instance_eval {@callbacks.empty?}
78
+ end
79
+
80
+ context "when adding an after_build callback" do
81
+ setup do
82
+ @the_block = lambda{|u| }
83
+ @factory.after_build &@the_block
84
+ end
85
+
86
+ should "have something in the set of callbacks" do
87
+ assert_equal 1, @factory.instance_eval {@callbacks.size}
88
+ end
89
+
90
+ should "record the callback in the set of callbacks" do
91
+ assert @factory.instance_eval {@callbacks.values}.include?(@the_block)
92
+ end
93
+
94
+ should "record the callback in the set of callbacks under the after_build key" do
95
+ assert_equal @the_block, @factory.instance_eval {@callbacks[:after_build]}
96
+ end
97
+ end
98
+
99
+ context "when adding an after_create callback" do
100
+ setup do
101
+ @the_block = lambda{|u| }
102
+ @factory.after_create &@the_block
103
+ end
104
+
105
+ should "have something in the set of callbacks" do
106
+ assert_equal 1, @factory.instance_eval {@callbacks.size}
107
+ end
108
+
109
+ should "record the callback in the set of callbacks" do
110
+ assert @factory.instance_eval {@callbacks.values}.include?(@the_block)
111
+ end
112
+
113
+ should "record the callback in the set of callbacks under the after_create key" do
114
+ assert_equal @the_block, @factory.instance_eval {@callbacks[:after_create]}
115
+ end
116
+ end
117
+
118
+ should "not allow the same attribute to be added twice" do
119
+ assert_raise(Factory::AttributeDefinitionError) do
120
+ 2.times { @factory.add_attribute @name }
121
+ end
122
+ end
123
+
124
+ context "when adding an attribute with a value parameter" do
125
+
126
+ setup do
127
+ @attr = :name
128
+ @value = 'Elvis lives!'
129
+ @factory.add_attribute(@attr, @value)
130
+ end
131
+
132
+ should "include that value in the generated attributes hash" do
133
+ assert_equal @value, @factory.attributes_for[@attr]
134
+ end
135
+
136
+ end
137
+
138
+ context "when adding an attribute with a block" do
139
+
140
+ setup do
141
+ @attr = :name
142
+ @attrs = {}
143
+ @proxy = mock('attr-proxy')
144
+ Factory::AttributeProxy.stubs(:new).returns(@proxy)
145
+ end
146
+
147
+ should "not evaluate the block when the attribute is added" do
148
+ @factory.add_attribute(@attr) { flunk }
149
+ end
150
+
151
+ should "evaluate the block when attributes are generated" do
152
+ called = false
153
+ @factory.add_attribute(@attr) do
154
+ called = true
155
+ end
156
+ @factory.attributes_for
157
+ assert called
158
+ end
159
+
160
+ should "use the result of the block as the value of the attribute" do
161
+ value = "Watch out for snakes!"
162
+ @factory.add_attribute(@attr) { value }
163
+ assert_equal value, @factory.attributes_for[@attr]
164
+ end
165
+
166
+ should "build an attribute proxy" do
167
+ Factory::AttributeProxy.expects(:new).with(@factory, @attr, :attributes_for, @attrs)
168
+ @factory.add_attribute(@attr) {}
169
+ @factory.attributes_for
170
+ end
171
+
172
+ should "yield an attribute proxy to the block" do
173
+ yielded = nil
174
+ @factory.add_attribute(@attr) {|y| yielded = y }
175
+ @factory.attributes_for
176
+ assert_equal @proxy, yielded
177
+ end
178
+
179
+ context "when other attributes have previously been defined" do
180
+
181
+ setup do
182
+ @attr = :unimportant
183
+ @attrs = {
184
+ :one => 'whatever',
185
+ :another => 'soup'
186
+ }
187
+ @factory.add_attribute(:one, 'whatever')
188
+ @factory.add_attribute(:another) { 'soup' }
189
+ @factory.add_attribute(@attr) {}
190
+ end
191
+
192
+ should "provide previously set attributes" do
193
+ Factory::AttributeProxy.expects(:new).with(@factory, @attr, :attributes_for, @attrs)
194
+ @factory.attributes_for
195
+ end
196
+
197
+ end
198
+
199
+ end
200
+
201
+ context "when adding an association without a factory name" do
202
+
203
+ setup do
204
+ @factory = Factory.new(:post)
205
+ @name = :user
206
+ @factory.association(@name)
207
+ Post.any_instance.stubs(:user=)
208
+ end
209
+
210
+ should "add an attribute with the name of the association" do
211
+ assert @factory.attributes_for.key?(@name)
212
+ end
213
+
214
+ should "create a block that builds the association" do
215
+ Factory.expects(:build).with(@name, {})
216
+ @factory.build
217
+ end
218
+
219
+ end
220
+
221
+ context "when adding an association with a factory name" do
222
+
223
+ setup do
224
+ @factory = Factory.new(:post)
225
+ @name = :author
226
+ @factory_name = :user
227
+ @factory.association(@name, :factory => @factory_name)
228
+ end
229
+
230
+ should "add an attribute with the name of the association" do
231
+ assert @factory.attributes_for.key?(@name)
232
+ end
233
+
234
+ should "create a block that builds the association" do
235
+ Factory.expects(:build).with(@factory_name, {})
236
+ @factory.build
237
+ end
238
+
239
+ end
240
+
241
+ context "specifying an association on a factory with a count" do
242
+ setup do
243
+ Factory.define(:post) { |f| f.name "Article" }
244
+ Factory.define(:user) do |u|
245
+ u.first_name "Joe"
246
+ u.last_name "Bloggs"
247
+ u.email "joe@example.com"
248
+ u.association :posts, :count => 5
249
+ end
250
+ @user = Factory(:user)
251
+ end
252
+
253
+ should "set up five associated post objects" do
254
+ assert_equal 5, @user.posts.size
255
+ end
256
+
257
+ should "have the user as the author on each object" do
258
+ @user.posts.each { |p| assert_equal @user, p.author }
259
+ end
260
+
261
+ should "have saved all the posts" do
262
+ @user.posts.each { |p| assert !p.new_record? }
263
+ end
264
+
265
+ end
266
+
267
+ should "add an attribute using the method name when passed an undefined method" do
268
+ @attr = :first_name
269
+ @value = 'Sugar'
270
+ @factory.send(@attr, @value)
271
+ assert_equal @value, @factory.attributes_for[@attr]
272
+ end
273
+
274
+ should "allow attributes to be added with strings as names" do
275
+ @factory.add_attribute('name', 'value')
276
+ assert_equal 'value', @factory.attributes_for[:name]
277
+ end
278
+
279
+ context "when overriding generated attributes with a hash" do
280
+
281
+ setup do
282
+ @attr = :name
283
+ @value = 'The price is right!'
284
+ @hash = { @attr => @value }
285
+ end
286
+
287
+ should "return the overridden value in the generated attributes" do
288
+ @factory.add_attribute(@attr, 'The price is wrong, Bob!')
289
+ assert_equal @value, @factory.attributes_for(@hash)[@attr]
290
+ end
291
+
292
+ should "not call a lazy attribute block for an overridden attribute" do
293
+ @factory.add_attribute(@attr) { flunk }
294
+ @factory.attributes_for(@hash)
295
+ end
296
+
297
+ should "override a symbol parameter with a string parameter" do
298
+ @factory.add_attribute(@attr, 'The price is wrong, Bob!')
299
+ @hash = { @attr.to_s => @value }
300
+ assert_equal @value, @factory.attributes_for(@hash)[@attr]
301
+ end
302
+
303
+ end
304
+
305
+ context "overriding an attribute with an alias" do
306
+
307
+ setup do
308
+ @factory.add_attribute(:test, 'original')
309
+ Factory.alias(/(.*)_alias/, '\1')
310
+ @result = @factory.attributes_for(:test_alias => 'new')
311
+ end
312
+
313
+ should "use the passed in value for the alias" do
314
+ assert_equal 'new', @result[:test_alias]
315
+ end
316
+
317
+ should "discard the predefined value for the attribute" do
318
+ assert_nil @result[:test]
319
+ end
320
+
321
+ end
322
+
323
+ should "guess the build class from the factory name" do
324
+ assert_equal User, @factory.build_class
325
+ end
326
+
327
+ context "when defined with a custom class" do
328
+
329
+ setup do
330
+ @class = User
331
+ @factory = Factory.new(:author, :class => @class)
332
+ end
333
+
334
+ should "use the specified class as the build class" do
335
+ assert_equal @class, @factory.build_class
336
+ end
337
+
338
+ end
339
+
340
+ context "when defined with a class instead of a name" do
341
+
342
+ setup do
343
+ @class = ArgumentError
344
+ @name = :argument_error
345
+ @factory = Factory.new(@class)
346
+ end
347
+
348
+ should "guess the name from the class" do
349
+ assert_equal @name, @factory.factory_name
350
+ end
351
+
352
+ should "use the class as the build class" do
353
+ assert_equal @class, @factory.build_class
354
+ end
355
+
356
+ end
357
+ context "when defined with a custom class name" do
358
+
359
+ setup do
360
+ @class = ArgumentError
361
+ @factory = Factory.new(:author, :class => :argument_error)
362
+ end
363
+
364
+ should "use the specified class as the build class" do
365
+ assert_equal @class, @factory.build_class
366
+ end
367
+
368
+ end
369
+
370
+ context "with some attributes added" do
371
+
372
+ setup do
373
+ @first_name = 'Billy'
374
+ @last_name = 'Idol'
375
+ @email = 'test@something.com'
376
+
377
+ @factory.add_attribute(:first_name, @first_name)
378
+ @factory.add_attribute(:last_name, @last_name)
379
+ @factory.add_attribute(:email, @email)
380
+ end
381
+
382
+ context "and an after_build callback has been registered" do
383
+ setup do
384
+ @the_block = lambda {|user| assert user.new_record?; @saved = user}
385
+
386
+ @factory.after_build &@the_block
387
+ end
388
+
389
+ should "call the callback when the object is built" do
390
+ @the_block.expects(:call).once
391
+ @factory.build
392
+ end
393
+
394
+ should "call the callback when the object is created" do
395
+ @the_block.expects(:call).once
396
+ @factory.create
397
+ end
398
+
399
+ should "yield the instance to the callback when called" do
400
+ instance = @factory.build
401
+ assert_equal @saved, instance
402
+ end
403
+ end
404
+
405
+ context "and an after_create callback has been registered" do
406
+ setup do
407
+ @the_block = lambda {|user| assert !user.new_record?; @saved = user}
408
+
409
+ @factory.after_create &@the_block
410
+ end
411
+
412
+ should "not call the callback when the object is built" do
413
+ @the_block.expects(:call).never
414
+ @factory.build
415
+ end
416
+
417
+ should "call the callback when the object is created" do
418
+ @the_block.expects(:call).once
419
+ @factory.create
420
+ end
421
+
422
+ should "yield the instance to the callback when called" do
423
+ instance = @factory.create
424
+ assert_equal @saved, instance
425
+ end
426
+ end
427
+
428
+ context "and both after_build and after_create callbacks have been registered" do
429
+ setup do
430
+ @the_after_build_block = lambda {|user| assert user.new_record?; @post_build = user}
431
+ @the_after_create_block = lambda {|user| assert !user.new_record?; @post_create = user}
432
+
433
+ @factory.after_build &@the_after_build_block
434
+ @factory.after_create &@the_after_create_block
435
+ end
436
+
437
+ should "only call the after_build callback when the object is built" do
438
+ @the_after_build_block.expects(:call).once
439
+ @the_after_create_block.expects(:call).never
440
+ @factory.build
441
+ end
442
+
443
+ should "call both callbacks when the object is created" do
444
+ @the_after_build_block.expects(:call).once
445
+ @the_after_create_block.expects(:call).once
446
+ @factory.create
447
+ end
448
+
449
+ should "yield the same instance to each callback when called" do
450
+ instance = @factory.create
451
+ assert_equal @post_build, instance
452
+ assert_equal @post_create, instance
453
+ assert_equal @post_create, @post_build
454
+ end
455
+
456
+ should "call the after_build callback before the after_create callback when objects are created" do
457
+ # TODO - is this good enough to detect "beforeness"?
458
+ @the_after_build_block = lambda {|user| assert_nil @post_build; assert_nil @post_create; @post_build = user}
459
+ @the_after_create_block = lambda {|user| assert_not_nil @post_build; assert_nil @post_create; @post_create = user}
460
+
461
+ @factory.after_build &@the_after_build_block
462
+ @factory.after_create &@the_after_create_block
463
+ @factory.create
464
+ end
465
+ end
466
+
467
+ context "when building an instance" do
468
+
469
+ setup do
470
+ @instance = @factory.build
471
+ end
472
+
473
+ should_instantiate_class
474
+
475
+ should "not save the instance" do
476
+ assert @instance.new_record?
477
+ end
478
+
479
+ end
480
+
481
+ context "when creating an instance" do
482
+
483
+ setup do
484
+ @instance = @factory.create
485
+ end
486
+
487
+ should_instantiate_class
488
+
489
+ should "save the instance" do
490
+ assert !@instance.new_record?
491
+ end
492
+
493
+ end
494
+
495
+ should "raise an ActiveRecord::RecordInvalid error for invalid instances" do
496
+ assert_raise(ActiveRecord::RecordInvalid) do
497
+ @factory.create(:first_name => nil)
498
+ end
499
+ end
500
+
501
+ end
502
+
503
+ end
504
+
505
+ context "a factory with a string for a name" do
506
+
507
+ setup do
508
+ @name = :user
509
+ @factory = Factory.new(@name.to_s) {}
510
+ end
511
+
512
+ should "convert the string to a symbol" do
513
+ assert_equal @name, @factory.factory_name
514
+ end
515
+
516
+ end
517
+
518
+ context "a factory defined with a string name" do
519
+
520
+ setup do
521
+ Factory.factories = {}
522
+ @name = :user
523
+ @factory = Factory.define(@name.to_s) {}
524
+ end
525
+
526
+ should "store the factory using a symbol" do
527
+ assert_equal @factory, Factory.factories[@name]
528
+ end
529
+
530
+ end
531
+
532
+ context "Factory class" do
533
+
534
+ setup do
535
+ @name = :user
536
+ @attrs = { :last_name => 'Override' }
537
+ @first_name = 'Johnny'
538
+ @last_name = 'Winter'
539
+ @class = User
540
+
541
+ Factory.define(@name) do |u|
542
+ u.first_name @first_name
543
+ u.last_name { @last_name }
544
+ u.email 'jwinter@guitar.org'
545
+ end
546
+
547
+ @factory = Factory.factories[@name]
548
+ end
549
+
550
+ [:build, :create, :attributes_for].each do |method|
551
+
552
+ should "delegate the #{method} method to the factory instance" do
553
+ @factory.expects(method).with(@attrs)
554
+ Factory.send(method, @name, @attrs)
555
+ end
556
+
557
+ should "raise an ArgumentError when #{method} is called with a nonexistant factory" do
558
+ assert_raise(ArgumentError) { Factory.send(method, :bogus) }
559
+ end
560
+
561
+ should "recognize either 'name' or :name for Factory.#{method}" do
562
+ assert_nothing_raised { Factory.send(method, @name.to_s) }
563
+ assert_nothing_raised { Factory.send(method, @name.to_sym) }
564
+ end
565
+
566
+ end
567
+
568
+ should "call the create method from the top-level Factory() method" do
569
+ @factory.expects(:create).with(@attrs)
570
+ Factory(@name, @attrs)
571
+ end
572
+
573
+ end
574
+
575
+ Factory.definition_file_paths.each do |file|
576
+ should "automatically load definitions from #{file}.rb" do
577
+ Factory.stubs(:require).raises(LoadError)
578
+ Factory.expects(:require).with(file)
579
+ Factory.find_definitions
580
+ end
581
+ end
582
+
583
+ should "only load the first set of factories detected" do
584
+ first, second, third = Factory.definition_file_paths
585
+ Factory.expects(:require).with(first).raises(LoadError)
586
+ Factory.expects(:require).with(second)
587
+ Factory.expects(:require).with(third).never
588
+ Factory.find_definitions
589
+ end
590
+
591
+ end