1
0
Fork 0
mirror of https://github.com/thoughtbot/factory_bot.git synced 2022-11-09 11:43:51 -05:00
thoughtbot--factory_bot/test/factory_test.rb

452 lines
12 KiB
Ruby

require(File.join(File.dirname(__FILE__), 'test_helper'))
class FactoryTest < Test::Unit::TestCase
def self.should_instantiate_class
should "instantiate the build class" do
assert_kind_of @class, @instance
end
should "assign attributes on the instance" do
assert_equal @first_name, @instance.first_name
assert_equal @last_name, @instance.last_name
end
should "override attributes using the passed hash" do
@value = 'Davis'
@instance = @factory.build(:first_name => @value)
assert_equal @value, @instance.first_name
end
end
context "defining a factory" do
setup do
@name = :user
@factory = mock('factory')
@factory.stubs(:factory_name).returns(@name)
@options = { :class => 'magic' }
Factory.stubs(:new).returns(@factory)
end
should "create a new factory using the specified name and options" do
Factory.expects(:new).with(@name, @options).returns(@factory)
Factory.define(@name, @options) {|f| }
end
should "pass the factory do the block" do
yielded = nil
Factory.define(@name) do |y|
yielded = y
end
assert_equal @factory, yielded
end
should "add the factory to the list of factories" do
Factory.define(@name) {|f| }
assert_equal Factory.factories[@name],
@factory,
"Factories: #{Factory.factories.inspect}"
end
end
context "a factory" do
setup do
@name = :user
@class = User
@factory = Factory.new(@name)
end
should "have a factory name" do
assert_equal @name, @factory.factory_name
end
should "have a build class" do
assert_equal @class, @factory.build_class
end
should "not allow the same attribute to be added twice" do
assert_raise(Factory::AttributeDefinitionError) do
2.times { @factory.add_attribute @name }
end
end
context "when adding an attribute with a value parameter" do
setup do
@attr = :name
@value = 'Elvis lives!'
@factory.add_attribute(@attr, @value)
end
should "include that value in the generated attributes hash" do
assert_equal @value, @factory.attributes_for[@attr]
end
end
context "when adding an attribute with a block" do
setup do
@attr = :name
@attrs = {}
@proxy = mock('attr-proxy')
Factory::AttributeProxy.stubs(:new).returns(@proxy)
end
should "not evaluate the block when the attribute is added" do
@factory.add_attribute(@attr) { flunk }
end
should "evaluate the block when attributes are generated" do
called = false
@factory.add_attribute(@attr) do
called = true
end
@factory.attributes_for
assert called
end
should "use the result of the block as the value of the attribute" do
value = "Watch out for snakes!"
@factory.add_attribute(@attr) { value }
assert_equal value, @factory.attributes_for[@attr]
end
should "build an attribute proxy" do
Factory::AttributeProxy.expects(:new).with(@factory, @attr, :attributes_for, @attrs)
@factory.add_attribute(@attr) {}
@factory.attributes_for
end
should "yield an attribute proxy to the block" do
yielded = nil
@factory.add_attribute(@attr) {|y| yielded = y }
@factory.attributes_for
assert_equal @proxy, yielded
end
context "when other attributes have previously been defined" do
setup do
@attr = :unimportant
@attrs = {
:one => 'whatever',
:another => 'soup'
}
@factory.add_attribute(:one, 'whatever')
@factory.add_attribute(:another) { 'soup' }
@factory.add_attribute(@attr) {}
end
should "provide previously set attributes" do
Factory::AttributeProxy.expects(:new).with(@factory, @attr, :attributes_for, @attrs)
@factory.attributes_for
end
end
end
context "when adding an association without a factory name" do
setup do
@factory = Factory.new(:post)
@name = :user
@factory.association(@name)
Post.any_instance.stubs(:user=)
end
should "add an attribute with the name of the association" do
assert @factory.attributes_for.key?(@name)
end
should "create a block that builds the association" do
Factory.expects(:build).with(@name, {})
@factory.build
end
end
context "when adding an association with a factory name" do
setup do
@factory = Factory.new(:post)
@name = :author
@factory_name = :user
@factory.association(@name, :factory => @factory_name)
end
should "add an attribute with the name of the association" do
assert @factory.attributes_for.key?(@name)
end
should "create a block that builds the association" do
Factory.expects(:build).with(@factory_name, {})
@factory.build
end
end
should "add an attribute using the method name when passed an undefined method" do
@attr = :first_name
@value = 'Sugar'
@factory.send(@attr, @value)
assert_equal @value, @factory.attributes_for[@attr]
end
should "allow attributes to be added with strings as names" do
@factory.add_attribute('name', 'value')
assert_equal 'value', @factory.attributes_for[:name]
end
context "when overriding generated attributes with a hash" do
setup do
@attr = :name
@value = 'The price is right!'
@hash = { @attr => @value }
end
should "return the overridden value in the generated attributes" do
@factory.add_attribute(@attr, 'The price is wrong, Bob!')
assert_equal @value, @factory.attributes_for(@hash)[@attr]
end
should "not call a lazy attribute block for an overridden attribute" do
@factory.add_attribute(@attr) { flunk }
@factory.attributes_for(@hash)
end
should "override a symbol parameter with a string parameter" do
@factory.add_attribute(@attr, 'The price is wrong, Bob!')
@hash = { @attr.to_s => @value }
assert_equal @value, @factory.attributes_for(@hash)[@attr]
end
end
context "overriding an attribute with an alias" do
setup do
@factory.add_attribute(:test, 'original')
Factory.alias(/(.*)_alias/, '\1')
@result = @factory.attributes_for(:test_alias => 'new')
end
should "use the passed in value for the alias" do
assert_equal 'new', @result[:test_alias]
end
should "discard the predefined value for the attribute" do
assert_nil @result[:test]
end
end
should "guess the build class from the factory name" do
assert_equal User, @factory.build_class
end
context "when defined with a custom class" do
setup do
@class = User
@factory = Factory.new(:author, :class => @class)
end
should "use the specified class as the build class" do
assert_equal @class, @factory.build_class
end
end
context "when defined with a class instead of a name" do
setup do
@class = ArgumentError
@name = :argument_error
@factory = Factory.new(@class)
end
should "guess the name from the class" do
assert_equal @name, @factory.factory_name
end
should "use the class as the build class" do
assert_equal @class, @factory.build_class
end
end
context "when defined with a custom class name" do
setup do
@class = ArgumentError
@factory = Factory.new(:author, :class => :argument_error)
end
should "use the specified class as the build class" do
assert_equal @class, @factory.build_class
end
end
context "with some attributes added" do
setup do
@first_name = 'Billy'
@last_name = 'Idol'
@email = 'test@something.com'
@factory.add_attribute(:first_name, @first_name)
@factory.add_attribute(:last_name, @last_name)
@factory.add_attribute(:email, @email)
end
context "when building an instance" do
setup do
@instance = @factory.build
end
should_instantiate_class
should "not save the instance" do
assert @instance.new_record?
end
end
context "when creating an instance" do
setup do
@instance = @factory.create
end
should_instantiate_class
should "save the instance" do
assert !@instance.new_record?
end
end
should "raise an ActiveRecord::RecordInvalid error for invalid instances" do
assert_raise(ActiveRecord::RecordInvalid) do
@factory.create(:first_name => nil)
end
end
end
end
context "a factory with a name ending in s" do
setup do
@name = :business
@class = Business
@factory = Factory.new(@name)
end
should "have a factory name" do
assert_equal @name, @factory.factory_name
end
should "have a build class" do
assert_equal @class, @factory.build_class
end
end
context "a factory with a string for a name" do
setup do
@name = :user
@factory = Factory.new(@name.to_s) {}
end
should "convert the string to a symbol" do
assert_equal @name, @factory.factory_name
end
end
context "a factory defined with a string name" do
setup do
Factory.factories = {}
@name = :user
@factory = Factory.define(@name.to_s) {}
end
should "store the factory using a symbol" do
assert_equal @factory, Factory.factories[@name]
end
end
context "Factory class" do
setup do
@name = :user
@attrs = { :last_name => 'Override' }
@first_name = 'Johnny'
@last_name = 'Winter'
@class = User
Factory.define(@name) do |u|
u.first_name @first_name
u.last_name { @last_name }
u.email 'jwinter@guitar.org'
end
@factory = Factory.factories[@name]
end
[:build, :create, :attributes_for].each do |method|
should "delegate the #{method} method to the factory instance" do
@factory.expects(method).with(@attrs)
Factory.send(method, @name, @attrs)
end
should "raise an ArgumentError when #{method} is called with a nonexistant factory" do
assert_raise(ArgumentError) { Factory.send(method, :bogus) }
end
should "recognize either 'name' or :name for Factory.#{method}" do
assert_nothing_raised { Factory.send(method, @name.to_s) }
assert_nothing_raised { Factory.send(method, @name.to_sym) }
end
end
should "call the create method from the top-level Factory() method" do
@factory.expects(:create).with(@attrs)
Factory(@name, @attrs)
end
end
Factory.definition_file_paths.each do |file|
should "automatically load definitions from #{file}.rb" do
Factory.stubs(:require).raises(LoadError)
Factory.expects(:require).with(file)
Factory.find_definitions
end
end
should "only load the first set of factories detected" do
first, second, third = Factory.definition_file_paths
Factory.expects(:require).with(first).raises(LoadError)
Factory.expects(:require).with(second)
Factory.expects(:require).with(third).never
Factory.find_definitions
end
end