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:
parent
d3a5d85485
commit
312bfa3528
2 changed files with 150 additions and 8 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue