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

Implemented build and create for Factory

This commit is contained in:
Joe Ferris 2008-05-28 21:07:51 -04:00
parent d3a5d85485
commit 312bfa3528
2 changed files with 150 additions and 8 deletions

View file

@ -12,19 +12,36 @@ class Factory
# Arguments: # Arguments:
# name: (Symbol) # name: (Symbol)
# A unique name used to identify this factory. # A unique name used to identify this factory.
# options: (Hash)
# class: the class that will be used when generating instances for this
# factory.
# #
# Yields: # Yields:
# The newly created factory (Factory) # The newly created factory (Factory)
def self.define (name) def self.define (name, options = {})
instance = Factory.new(name) instance = Factory.new(name, options)
yield(instance) yield(instance)
self.factories << instance self.factories << instance
end end
def initialize (name) #:nodoc: # Calculates the class that should be instantiated by generation methods.
@name = name #
# If a class was passed when defining this factory, that class will be
# returned. Otherwise, the class will be guessed from the factory name.
#
# Returns:
# The class that will be instantiated by generation methods.
def build_class
@build_class ||= @options[:class] || name.to_s.classify.constantize
end
def initialize (name, options = {}) #:nodoc:
options.assert_valid_keys(:class)
@name = name
@options = options
@static_attributes = {} @static_attributes = {}
@lazy_attributes = {} @lazy_attributes = {}
end end
# Adds an attribute that should be assigned or stubbed on generated instances for this factory. # Adds an attribute that should be assigned or stubbed on generated instances for this factory.
@ -72,4 +89,42 @@ class Factory
result.update(attrs) result.update(attrs)
end end
# Generates and returns an instance from this factory. Attributes can be
# individually overridden by passing in a Hash of attribute => value pairs.
#
# Arguments:
# attrs: (Hash)
# See attributes
#
# Returns:
# An instance of the class this factory generates, with generated
# attributes assigned.
def build (attrs = {})
instance = build_class.new
attributes(attrs).each do |attr, value|
instance.send(:"#{attr}=", value)
end
instance
end
# Generates, saves, and returns an instance from this factory. Attributes can
# be individually overridden by passing in a Hash of attribute => value
# pairs.
#
# If the instance is not valid, an ActiveRecord::Invalid exception will be
# raised.
#
# Arguments:
# attrs: (Hash)
# See attributes
#
# Returns:
# A saved instance of the class this factory generates, with generated
# attributes assigned.
def create (attrs = {})
instance = build(attrs)
instance.save!
instance
end
end end

View file

@ -2,17 +2,37 @@ require(File.join(File.dirname(__FILE__), 'test_helper'))
class FactoryTest < Test::Unit::TestCase 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 context "defining a factory" do
setup do setup do
@name = :user @name = :user
@factory = mock('factory') @factory = mock('factory')
@options = { :class => 'magic' }
Factory.stubs(:new).returns(@factory) Factory.stubs(:new).returns(@factory)
end end
should "create a new factory" do should "create a new factory using the specified name and options" do
Factory.expects(:new).with(@name) Factory.expects(:new).with(@name, @options)
Factory.define(@name) {|f| } Factory.define(@name, @options) {|f| }
end end
should "pass the factory do the block" do should "pass the factory do the block" do
@ -35,6 +55,7 @@ class FactoryTest < Test::Unit::TestCase
setup do setup do
@name = :user @name = :user
@class = User
@factory = Factory.new(@name) @factory = Factory.new(@name)
end end
@ -42,6 +63,10 @@ class FactoryTest < Test::Unit::TestCase
assert_equal @name, @factory.name assert_equal @name, @factory.name
end end
should "have a build class" do
assert_equal @class, @factory.build_class
end
context "when adding an attribute with a value parameter" do context "when adding an attribute with a value parameter" do
setup do setup do
@ -109,6 +134,68 @@ class FactoryTest < Test::Unit::TestCase
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 "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
end
context "when creating an instance" do
setup do
User.delete_all
@instance = @factory.create
end
should_instantiate_class
should "save the instance" do
assert_equal 1, @class.count
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 end
end end