diff --git a/lib/factory_girl.rb b/lib/factory_girl.rb index afe86db..6336eea 100644 --- a/lib/factory_girl.rb +++ b/lib/factory_girl.rb @@ -11,6 +11,8 @@ require 'factory_girl/attribute/association' require 'factory_girl/attribute/callback' require 'factory_girl/sequence' require 'factory_girl/aliases' +require 'factory_girl/definition_proxy' +require 'factory_girl/syntax/default' # Shortcut for Factory.default_strategy. # diff --git a/lib/factory_girl/definition_proxy.rb b/lib/factory_girl/definition_proxy.rb new file mode 100644 index 0000000..1091f70 --- /dev/null +++ b/lib/factory_girl/definition_proxy.rb @@ -0,0 +1,122 @@ +class Factory + class DefinitionProxy + instance_methods.each do |method| + undef_method(method) unless method =~ /(^__|^nil\?$|^send$|^object_id$|^extend$|^instance_eval$)/ + end + + def initialize(factory) + @factory = factory + end + + # Adds an attribute that should be assigned on generated instances for this + # factory. + # + # This method should be called with either a value or block, but not both. If + # called with a block, the attribute will be generated "lazily," whenever an + # instance is generated. Lazy attribute blocks will not be called if that + # attribute is overridden for a specific instance. + # + # When defining lazy attributes, an instance of Factory::Proxy will + # be yielded, allowing associations to be built using the correct build + # strategy. + # + # Arguments: + # * name: +Symbol+ or +String+ + # The name of this attribute. This will be assigned using :"#{name}=" for + # generated instances. + # * value: +Object+ + # If no block is given, this value will be used for this attribute. + def add_attribute (name, value = nil, &block) + if block_given? + if value + raise AttributeDefinitionError, "Both value and block given" + else + attribute = Attribute::Dynamic.new(name, block) + end + else + attribute = Attribute::Static.new(name, value) + end + + @factory.define_attribute(attribute) + end + + # Calls add_attribute using the missing method name as the name of the + # attribute, so that: + # + # Factory.define :user do |f| + # f.name 'Billy Idol' + # end + # + # and: + # + # Factory.define :user do |f| + # f.add_attribute :name, 'Billy Idol' + # end + # + # are equivilent. + def method_missing (name, *args, &block) + add_attribute(name, *args, &block) + end + + # Adds an attribute that will have unique values generated by a sequence with + # a specified format. + # + # The result of: + # Factory.define :user do |f| + # f.sequence(:email) { |n| "person#{n}@example.com" } + # end + # + # Is equal to: + # Factory.sequence(:email) { |n| "person#{n}@example.com" } + # + # Factory.define :user do |f| + # f.email { Factory.next(:email) } + # end + # + # Except that no globally available sequence will be defined. + def sequence(name, &block) + sequence = Sequence.new(&block) + add_attribute(name) { sequence.next } + end + + # Adds an attribute that builds an association. The associated instance will + # be built using the same build strategy as the parent instance. + # + # Example: + # Factory.define :user do |f| + # f.name 'Joey' + # end + # + # Factory.define :post do |f| + # f.association :author, :factory => :user + # end + # + # Arguments: + # * name: +Symbol+ + # The name of this attribute. + # * options: +Hash+ + # + # Options: + # * factory: +Symbol+ or +String+ + # The name of the factory to use when building the associated instance. + # If no name is given, the name of the attribute is assumed to be the + # name of the factory. For example, a "user" association will by + # default use the "user" factory. + def association(name, options = {}) + factory_name = options.delete(:factory) || name + @factory.define_attribute(Attribute::Association.new(name, factory_name, options)) + end + + def after_build(&block) + @factory.add_callback(:after_build, &block) + end + + def after_create(&block) + @factory.add_callback(:after_create, &block) + end + + def after_stub(&block) + @factory.add_callback(:after_stub, &block) + end + end +end diff --git a/lib/factory_girl/factory.rb b/lib/factory_girl/factory.rb index e994f30..905e9ca 100644 --- a/lib/factory_girl/factory.rb +++ b/lib/factory_girl/factory.rb @@ -1,7 +1,4 @@ class Factory - undef :id if Factory.instance_methods.include?('id') - undef :type if Factory.instance_methods.include?('type') - # Raised when a factory is defined that attempts to instantiate itself. class AssociationDefinitionError < RuntimeError end @@ -30,37 +27,12 @@ class Factory attr_reader :factory_name #:nodoc: attr_reader :attributes #:nodoc: - # Defines a new factory that can be used by the build strategies (create and - # build) to build new objects. - # - # Arguments: - # * name: +Symbol+ or +String+ - # A unique name used to identify this factory. - # * options: +Hash+ - # - # Options: - # * class: +Symbol+, +Class+, or +String+ - # The class that will be used when generating instances for this factory. If not specified, the class will be guessed from the factory name. - # * parent: +Symbol+ - # The parent factory. If specified, the attributes from the parent - # factory will be copied to the current one with an ability to override - # them. - # * default_strategy: +Symbol+ - # The strategy that will be used by the Factory shortcut method. - # Defaults to :create. - # - # Yields: +Factory+ - # The newly created factory. - def self.define (name, options = {}) - instance = Factory.new(name, options) - yield(instance) - if parent = options.delete(:parent) - instance.inherit_from(Factory.factory_by_name(parent)) - end - if self.factories[instance.factory_name] + def self.register_factory(factory) + name = factory.factory_name + if self.factories[name] raise DuplicateDefinitionError, "Factory already defined: #{name}" end - self.factories[instance.factory_name] = instance + self.factories[name] = factory end def class_name #:nodoc: @@ -92,215 +64,25 @@ class Factory end end - # Adds an attribute that should be assigned on generated instances for this - # factory. - # - # This method should be called with either a value or block, but not both. If - # called with a block, the attribute will be generated "lazily," whenever an - # instance is generated. Lazy attribute blocks will not be called if that - # attribute is overridden for a specific instance. - # - # When defining lazy attributes, an instance of Factory::Proxy will - # be yielded, allowing associations to be built using the correct build - # strategy. - # - # Arguments: - # * name: +Symbol+ or +String+ - # The name of this attribute. This will be assigned using :"#{name}=" for - # generated instances. - # * value: +Object+ - # If no block is given, this value will be used for this attribute. - def add_attribute (name, value = nil, &block) - if block_given? - if value - raise AttributeDefinitionError, "Both value and block given" - else - attribute = Attribute::Dynamic.new(name, block) - end - else - attribute = Attribute::Static.new(name, value) - end - - if attribute_defined?(attribute.name) + def define_attribute(attribute) + name = attribute.name + # TODO: move these checks into Attribute + if attribute_defined?(name) raise AttributeDefinitionError, "Attribute already defined: #{name}" end - + if attribute.respond_to?(:factory) && attribute.factory == self.factory_name + raise AssociationDefinitionError, "Self-referencing association '#{name}' in factory '#{self.factory_name}'" + end @attributes << attribute end - # Calls add_attribute using the missing method name as the name of the - # attribute, so that: - # - # Factory.define :user do |f| - # f.name 'Billy Idol' - # end - # - # and: - # - # Factory.define :user do |f| - # f.add_attribute :name, 'Billy Idol' - # end - # - # are equivilent. - def method_missing (name, *args, &block) - add_attribute(name, *args, &block) - end - - # Adds an attribute that builds an association. The associated instance will - # be built using the same build strategy as the parent instance. - # - # Example: - # Factory.define :user do |f| - # f.name 'Joey' - # end - # - # Factory.define :post do |f| - # f.association :author, :factory => :user - # end - # - # Arguments: - # * name: +Symbol+ - # The name of this attribute. - # * options: +Hash+ - # - # Options: - # * factory: +Symbol+ or +String+ - # The name of the factory to use when building the associated instance. - # If no name is given, the name of the attribute is assumed to be the - # name of the factory. For example, a "user" association will by - # default use the "user" factory. - def association (name, options = {}) - factory_name = options.delete(:factory) || name - if factory_name_for(factory_name) == self.factory_name - raise AssociationDefinitionError, "Self-referencing association '#{name}' in factory '#{self.factory_name}'" - end - @attributes << Attribute::Association.new(name, factory_name, options) - end - - # Adds an attribute that will have unique values generated by a sequence with - # a specified format. - # - # The result of: - # Factory.define :user do |f| - # f.sequence(:email) { |n| "person#{n}@example.com" } - # end - # - # Is equal to: - # Factory.sequence(:email) { |n| "person#{n}@example.com" } - # - # Factory.define :user do |f| - # f.email { Factory.next(:email) } - # end - # - # Except that no globally available sequence will be defined. - def sequence (name, &block) - s = Sequence.new(&block) - add_attribute(name) { s.next } - end - - def after_build(&block) - callback(:after_build, &block) - end - - def after_create(&block) - callback(:after_create, &block) - end - - def after_stub(&block) - callback(:after_stub, &block) - end - - def callback(name, &block) + def add_callback(name, &block) unless [:after_build, :after_create, :after_stub].include?(name.to_sym) raise InvalidCallbackNameError, "#{name} is not a valid callback name. Valid callback names are :after_build, :after_create, and :after_stub" end @attributes << Attribute::Callback.new(name.to_sym, block) end - # Generates and returns a Hash of attributes from this factory. Attributes - # can be individually overridden by passing in a Hash of attribute => value - # pairs. - # - # Arguments: - # * name: +Symbol+ or +String+ - # The name of the factory that should be used. - # * overrides: +Hash+ - # Attributes to overwrite for this set. - # - # Returns: +Hash+ - # A set of attributes that can be used to build an instance of the class - # this factory generates. - def self.attributes_for (name, overrides = {}) - factory_by_name(name).run(Proxy::AttributesFor, overrides) - end - - # Generates and returns an instance from this factory. Attributes can be - # individually overridden by passing in a Hash of attribute => value pairs. - # - # Arguments: - # * name: +Symbol+ or +String+ - # The name of the factory that should be used. - # * overrides: +Hash+ - # Attributes to overwrite for this instance. - # - # Returns: +Object+ - # An instance of the class this factory generates, with generated attributes - # assigned. - def self.build (name, overrides = {}) - factory_by_name(name).run(Proxy::Build, overrides) - end - - # Generates, saves, and returns an instance from this factory. Attributes can - # be individually overridden by passing in a Hash of attribute => value - # pairs. - # - # Instances are saved using the +save!+ method, so ActiveRecord models will - # raise ActiveRecord::RecordInvalid exceptions for invalid attribute sets. - # - # Arguments: - # * name: +Symbol+ or +String+ - # The name of the factory that should be used. - # * overrides: +Hash+ - # Attributes to overwrite for this instance. - # - # Returns: +Object+ - # A saved instance of the class this factory generates, with generated - # attributes assigned. - def self.create (name, overrides = {}) - factory_by_name(name).run(Proxy::Create, overrides) - end - - # Generates and returns an object with all attributes from this factory - # stubbed out. Attributes can be individually overridden by passing in a Hash - # of attribute => value pairs. - # - # Arguments: - # * name: +Symbol+ or +String+ - # The name of the factory that should be used. - # * overrides: +Hash+ - # Attributes to overwrite for this instance. - # - # Returns: +Object+ - # An object with generated attributes stubbed out. - def self.stub (name, overrides = {}) - factory_by_name(name).run(Proxy::Stub, overrides) - end - - # Executes the default strategy for the given factory. This is usually create, - # but it can be overridden for each factory. - # - # Arguments: - # * name: +Symbol+ or +String+ - # The name of the factory that should be used. - # * overrides: +Hash+ - # Attributes to overwrite for this instance. - # - # Returns: +Object+ - # The result of the default strategy. - def self.default_strategy (name, overrides = {}) - self.send(factory_by_name(name).default_strategy, name, overrides) - end - def self.find_definitions #:nodoc: definition_file_paths.each do |path| require("#{path}.rb") if File.exists?("#{path}.rb") diff --git a/lib/factory_girl/syntax/blueprint.rb b/lib/factory_girl/syntax/blueprint.rb index 74704c4..0aa2626 100644 --- a/lib/factory_girl/syntax/blueprint.rb +++ b/lib/factory_girl/syntax/blueprint.rb @@ -27,8 +27,9 @@ class Factory def blueprint(&block) instance = Factory.new(name.underscore, :class => self) - instance.instance_eval(&block) - Factory.factories[instance.factory_name] = instance + proxy = Factory::DefinitionProxy.new(instance) + proxy.instance_eval(&block) + Factory.register_factory(instance) end end diff --git a/lib/factory_girl/syntax/default.rb b/lib/factory_girl/syntax/default.rb new file mode 100644 index 0000000..55d6ad0 --- /dev/null +++ b/lib/factory_girl/syntax/default.rb @@ -0,0 +1,118 @@ +class Factory + + # Defines a new factory that can be used by the build strategies (create and + # build) to build new objects. + # + # Arguments: + # * name: +Symbol+ or +String+ + # A unique name used to identify this factory. + # * options: +Hash+ + # + # Options: + # * class: +Symbol+, +Class+, or +String+ + # The class that will be used when generating instances for this factory. If not specified, the class will be guessed from the factory name. + # * parent: +Symbol+ + # The parent factory. If specified, the attributes from the parent + # factory will be copied to the current one with an ability to override + # them. + # * default_strategy: +Symbol+ + # The strategy that will be used by the Factory shortcut method. + # Defaults to :create. + # + # Yields: +Factory+ + # The newly created factory. + def self.define(name, options = {}) + factory = Factory.new(name, options) + proxy = Factory::DefinitionProxy.new(factory) + yield(proxy) + if parent = options.delete(:parent) + factory.inherit_from(Factory.factory_by_name(parent)) + end + register_factory(factory) + end + + # Generates and returns a Hash of attributes from this factory. Attributes + # can be individually overridden by passing in a Hash of attribute => value + # pairs. + # + # Arguments: + # * name: +Symbol+ or +String+ + # The name of the factory that should be used. + # * overrides: +Hash+ + # Attributes to overwrite for this set. + # + # Returns: +Hash+ + # A set of attributes that can be used to build an instance of the class + # this factory generates. + def self.attributes_for (name, overrides = {}) + factory_by_name(name).run(Proxy::AttributesFor, overrides) + end + + # Generates and returns an instance from this factory. Attributes can be + # individually overridden by passing in a Hash of attribute => value pairs. + # + # Arguments: + # * name: +Symbol+ or +String+ + # The name of the factory that should be used. + # * overrides: +Hash+ + # Attributes to overwrite for this instance. + # + # Returns: +Object+ + # An instance of the class this factory generates, with generated attributes + # assigned. + def self.build (name, overrides = {}) + factory_by_name(name).run(Proxy::Build, overrides) + end + + # Generates, saves, and returns an instance from this factory. Attributes can + # be individually overridden by passing in a Hash of attribute => value + # pairs. + # + # Instances are saved using the +save!+ method, so ActiveRecord models will + # raise ActiveRecord::RecordInvalid exceptions for invalid attribute sets. + # + # Arguments: + # * name: +Symbol+ or +String+ + # The name of the factory that should be used. + # * overrides: +Hash+ + # Attributes to overwrite for this instance. + # + # Returns: +Object+ + # A saved instance of the class this factory generates, with generated + # attributes assigned. + def self.create (name, overrides = {}) + factory_by_name(name).run(Proxy::Create, overrides) + end + + # Generates and returns an object with all attributes from this factory + # stubbed out. Attributes can be individually overridden by passing in a Hash + # of attribute => value pairs. + # + # Arguments: + # * name: +Symbol+ or +String+ + # The name of the factory that should be used. + # * overrides: +Hash+ + # Attributes to overwrite for this instance. + # + # Returns: +Object+ + # An object with generated attributes stubbed out. + def self.stub (name, overrides = {}) + factory_by_name(name).run(Proxy::Stub, overrides) + end + + # Executes the default strategy for the given factory. This is usually create, + # but it can be overridden for each factory. + # + # Arguments: + # * name: +Symbol+ or +String+ + # The name of the factory that should be used. + # * overrides: +Hash+ + # Attributes to overwrite for this instance. + # + # Returns: +Object+ + # The result of the default strategy. + def self.default_strategy (name, overrides = {}) + self.send(factory_by_name(name).default_strategy, name, overrides) + end + +end diff --git a/spec/acceptance/acceptance_spec.rb b/spec/acceptance/acceptance_spec.rb index 74fa465..bc1f3e7 100644 --- a/spec/acceptance/acceptance_spec.rb +++ b/spec/acceptance/acceptance_spec.rb @@ -39,7 +39,7 @@ describe "integration" do end Factory.define :user_with_inherited_callbacks, :parent => :user_with_callbacks do |f| - f.callback(:after_stub) {|u| u.last_name = 'Double-Stubby' } + f.after_stub {|u| u.last_name = 'Double-Stubby' } end Factory.define :business do |f| diff --git a/spec/acceptance/syntax/blueprint_spec.rb b/spec/acceptance/syntax/blueprint_spec.rb index d6e9605..659f5f6 100644 --- a/spec/acceptance/syntax/blueprint_spec.rb +++ b/spec/acceptance/syntax/blueprint_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' +require 'acceptance/acceptance_helper' require 'factory_girl/syntax/blueprint' @@ -12,11 +13,6 @@ describe "a blueprint" do end end - after do - Factory.factories.clear - Factory.sequences.clear - end - describe "after making an instance" do before do @instance = Factory(:user, :last_name => 'Rye') diff --git a/spec/acceptance/syntax/default_spec.rb b/spec/acceptance/syntax/default_spec.rb new file mode 100644 index 0000000..f34ecb0 --- /dev/null +++ b/spec/acceptance/syntax/default_spec.rb @@ -0,0 +1,143 @@ +require 'spec_helper' +require 'acceptance/acceptance_helper' + +describe "default syntax" do + before do + Factory.sequence(:email) { |n| "somebody#{n}@example.com" } + Factory.define :user do |factory| + factory.first_name { 'Bill' } + factory.last_name { 'Nye' } + factory.email { Factory.next(:email) } + end + end + + after do + Factory.factories.clear + Factory.sequences.clear + end + + describe "after making an instance" do + before do + @instance = Factory(:user, :last_name => 'Rye') + end + + it "should use attributes from the definition" do + @instance.first_name.should == 'Bill' + end + + it "should evaluate attribute blocks for each instance" do + @instance.email.should =~ /somebody\d+@example.com/ + Factory(:user).email.should_not == @instance.email + end + end + + it "should raise an ArgumentError when trying to use a non-existent strategy" do + lambda { + Factory.define(:object, :default_strategy => :nonexistent) {} + }.should raise_error(ArgumentError) + end +end + +describe Factory, "given a parent factory" do + before do + @parent = Factory.new(:object) + @parent.define_attribute(Factory::Attribute::Static.new(:name, 'value')) + Factory.register_factory(@parent) + end + + it "should raise an ArgumentError when trying to use a non-existent factory as parent" do + lambda { + Factory.define(:child, :parent => :nonexsitent) {} + }.should raise_error(ArgumentError) + end +end + +describe "defining a factory" do + before do + @name = :user + @factory = "factory" + @proxy = "proxy" + stub(@factory).factory_name { @name } + @options = { :class => 'magic' } + stub(Factory).new { @factory } + stub(Factory::DefinitionProxy).new { @proxy } + end + + after { Factory.factories.clear } + + it "should create a new factory using the specified name and options" do + mock(Factory).new(@name, @options) { @factory } + Factory.define(@name, @options) {|f| } + end + + it "should pass the factory do the block" do + yielded = nil + Factory.define(@name) do |y| + yielded = y + end + yielded.should == @proxy + end + + it "should add the factory to the list of factories" do + Factory.define(@name) {|f| } + @factory.should == Factory.factories[@name] + end + + it "should allow a factory to be found by name" do + Factory.define(@name) {|f| } + Factory.factory_by_name(@name).should == @factory + end +end + +describe "after defining a factory" do + before do + @name = :user + @factory = "factory" + + Factory.factories[@name] = @factory + end + + it "should use Proxy::AttributesFor for Factory.attributes_for" do + mock(@factory).run(Factory::Proxy::AttributesFor, :attr => 'value') { 'result' } + Factory.attributes_for(@name, :attr => 'value').should == 'result' + end + + it "should use Proxy::Build for Factory.build" do + mock(@factory).run(Factory::Proxy::Build, :attr => 'value') { 'result' } + Factory.build(@name, :attr => 'value').should == 'result' + end + + it "should use Proxy::Create for Factory.create" do + mock(@factory).run(Factory::Proxy::Create, :attr => 'value') { 'result' } + Factory.create(@name, :attr => 'value').should == 'result' + end + + it "should use Proxy::Stub for Factory.stub" do + mock(@factory).run(Factory::Proxy::Stub, :attr => 'value') { 'result' } + Factory.stub(@name, :attr => 'value').should == 'result' + end + + it "should use default strategy option as Factory.default_strategy" do + stub(@factory).default_strategy { :create } + mock(@factory).run(Factory::Proxy::Create, :attr => 'value') { 'result' } + Factory.default_strategy(@name, :attr => 'value').should == 'result' + end + + it "should use the default strategy for the global Factory method" do + stub(@factory).default_strategy { :create } + mock(@factory).run(Factory::Proxy::Create, :attr => 'value') { 'result' } + Factory(@name, :attr => 'value').should == 'result' + end + + [:build, :create, :attributes_for, :stub].each do |method| + it "should raise an ArgumentError on #{method} with a nonexistant factory" do + lambda { Factory.send(method, :bogus) }.should raise_error(ArgumentError) + end + + it "should recognize either 'name' or :name for Factory.#{method}" do + stub(@factory).run + lambda { Factory.send(method, @name.to_s) }.should_not raise_error + lambda { Factory.send(method, @name.to_sym) }.should_not raise_error + end + end +end diff --git a/spec/acceptance/syntax/generate_spec.rb b/spec/acceptance/syntax/generate_spec.rb index 4aa806e..b77c3bd 100644 --- a/spec/acceptance/syntax/generate_spec.rb +++ b/spec/acceptance/syntax/generate_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' +require 'acceptance/acceptance_helper' require 'factory_girl/syntax/generate' @@ -11,10 +12,6 @@ describe "a factory using generate syntax" do end end - after do - Factory.factories.clear - end - it "should not raise an error when generating an invalid instance" do lambda { User.generate(:first_name => nil) }.should_not raise_error end diff --git a/spec/factory_girl/definition_proxy_spec.rb b/spec/factory_girl/definition_proxy_spec.rb new file mode 100644 index 0000000..e155e9d --- /dev/null +++ b/spec/factory_girl/definition_proxy_spec.rb @@ -0,0 +1,100 @@ +require 'spec_helper' + +describe Factory::DefinitionProxy do + let(:factory) { Factory.new(:object) } + subject { Factory::DefinitionProxy.new(factory) } + + it "should add a static attribute for type" do + subject.type + factory.attributes.last.should be_kind_of(Factory::Attribute::Static) + end + + it "should add a static attribute for id" do + subject.id + factory.attributes.last.should be_kind_of(Factory::Attribute::Static) + end + + it "should add a static attribute when an attribute is defined with a value" do + attribute = 'attribute' + stub(attribute).name { :name } + mock(Factory::Attribute::Static).new(:name, 'value') { attribute } + mock(factory).define_attribute(attribute) + subject.add_attribute(:name, 'value') + end + + it "should add a dynamic attribute when an attribute is defined with a block" do + attribute = 'attribute' + stub(attribute).name { :name } + block = lambda {} + mock(Factory::Attribute::Dynamic).new(:name, block) { attribute } + mock(factory).define_attribute(attribute) + subject.add_attribute(:name, &block) + end + + it "should raise for an attribute with a value and a block" do + lambda { + subject.add_attribute(:name, 'value') {} + }.should raise_error(Factory::AttributeDefinitionError) + end + + describe "adding an attribute using a in-line sequence" do + it "should create the sequence" do + mock(Factory::Sequence).new + subject.sequence(:name) {} + end + + it "should add a dynamic attribute" do + attribute = 'attribute' + stub(attribute).name { :name } + mock(Factory::Attribute::Dynamic).new(:name, is_a(Proc)) { attribute } + subject.sequence(:name) {} + factory.attributes.should include(attribute) + end + end + + it "should add a callback attribute when the after_build attribute is defined" do + mock(Factory::Attribute::Callback).new(:after_build, is_a(Proc)) { 'after_build callback' } + subject.after_build {} + factory.attributes.should include('after_build callback') + end + + it "should add a callback attribute when the after_create attribute is defined" do + mock(Factory::Attribute::Callback).new(:after_create, is_a(Proc)) { 'after_create callback' } + subject.after_create {} + factory.attributes.should include('after_create callback') + end + + it "should add a callback attribute when the after_stub attribute is defined" do + mock(Factory::Attribute::Callback).new(:after_stub, is_a(Proc)) { 'after_stub callback' } + subject.after_stub {} + factory.attributes.should include('after_stub callback') + end + + it "should add an association without a factory name or overrides" do + name = :user + attr = 'attribute' + stub(attr).name { name } + mock(Factory::Attribute::Association).new(name, name, {}) { attr } + subject.association(name) + factory.attributes.should include(attr) + end + + it "should add an association with overrides" do + name = :user + attr = 'attribute' + overrides = { :first_name => 'Ben' } + stub(attr).name { name } + mock(Factory::Attribute::Association).new(name, name, overrides) { attr } + subject.association(name, overrides) + factory.attributes.should include(attr) + end + + it "should add an attribute using the method name when passed an undefined method" do + attribute = 'attribute' + stub(attribute).name { :name } + block = lambda {} + mock(Factory::Attribute::Static).new(:name, 'value') { attribute } + subject.send(:name, 'value') + factory.attributes.should include(attribute) + end +end diff --git a/spec/factory_girl/factory_spec.rb b/spec/factory_girl/factory_spec.rb index 5478d56..678abe9 100644 --- a/spec/factory_girl/factory_spec.rb +++ b/spec/factory_girl/factory_spec.rb @@ -1,581 +1,361 @@ require 'spec_helper' +describe Factory, "registering a factory" do + before do + @name = :user + @factory = "factory" + stub(@factory).factory_name { @name } + end + + after { Factory.factories.clear } + + it "should add the factory to the list of factories" do + Factory.register_factory(@factory) + Factory.factory_by_name(@name).should == @factory + end + + it "should not allow a duplicate factory definition" do + lambda { + 2.times { Factory.register_factory(@factory) } + }.should raise_error(Factory::DuplicateDefinitionError) + end +end + +describe Factory do + include DefinesConstants + + before do + @name = :user + @class = define_constant('User') + @factory = Factory.new(@name) + end + + it "should have a factory name" do + @factory.factory_name.should == @name + end + + it "should have a build class" do + @factory.build_class.should == @class + end + + it "should have a default strategy" do + @factory.default_strategy.should == :create + end + + it "should not allow the same attribute to be added twice" do + lambda { + 2.times { @factory.define_attribute Factory::Attribute::Static.new(:name, 'value') } + }.should raise_error(Factory::AttributeDefinitionError) + end + + it "should add a callback attribute when defining a callback" do + mock(Factory::Attribute::Callback).new(:after_create, is_a(Proc)) { 'after_create callback' } + @factory.add_callback(:after_create) {} + @factory.attributes.should include('after_create callback') + end + + it "should raise an InvalidCallbackNameError when defining a callback with an invalid name" do + lambda{ + @factory.add_callback(:invalid_callback_name) {} + }.should raise_error(Factory::InvalidCallbackNameError) + end + + describe "after adding an attribute" do + before do + @attribute = "attribute" + @proxy = "proxy" + + stub(@attribute).name { :name } + stub(@attribute).add_to + stub(@proxy).set + stub(@proxy).result { 'result' } + stub(Factory::Attribute::Static).new { @attribute } + stub(Factory::Proxy::Build).new { @proxy } + + @factory.define_attribute(@attribute) + end + + it "should create the right proxy using the build class when running" do + mock(Factory::Proxy::Build).new(@factory.build_class) { @proxy } + @factory.run(Factory::Proxy::Build, {}) + end + + it "should add the attribute to the proxy when running" do + mock(@attribute).add_to(@proxy) + @factory.run(Factory::Proxy::Build, {}) + end + + it "should return the result from the proxy when running" do + mock(@proxy).result() { 'result' } + @factory.run(Factory::Proxy::Build, {}).should == 'result' + end + end + + it "should return associations" do + factory = Factory.new(:post) + factory.define_attribute(Factory::Attribute::Association.new(:author, :author, {})) + factory.define_attribute(Factory::Attribute::Association.new(:editor, :editor, {})) + factory.associations.each do |association| + association.should be_a(Factory::Attribute::Association) + end + factory.associations.size.should == 2 + end + + it "should raise for a self referencing association" do + factory = Factory.new(:post) + lambda { + factory.define_attribute(Factory::Attribute::Association.new(:parent, :post, {})) + }.should raise_error(Factory::AssociationDefinitionError) + end + + describe "when overriding generated attributes with a hash" do + before do + @name = :name + @value = 'The price is right!' + @hash = { @name => @value } + end + + it "should return the overridden value in the generated attributes" do + attr = Factory::Attribute::Static.new(@name, 'The price is wrong, Bob!') + @factory.define_attribute(attr) + result = @factory.run(Factory::Proxy::AttributesFor, @hash) + result[@name].should == @value + end + + it "should not call a lazy attribute block for an overridden attribute" do + attr = Factory::Attribute::Dynamic.new(@name, lambda { flunk }) + @factory.define_attribute(attr) + result = @factory.run(Factory::Proxy::AttributesFor, @hash) + end + + it "should override a symbol parameter with a string parameter" do + attr = Factory::Attribute::Static.new(@name, 'The price is wrong, Bob!') + @factory.define_attribute(attr) + @hash = { @name.to_s => @value } + result = @factory.run(Factory::Proxy::AttributesFor, @hash) + result[@name].should == @value + end + end + + describe "overriding an attribute with an alias" do + before do + @factory.define_attribute(Factory::Attribute::Static.new(:test, 'original')) + Factory.alias(/(.*)_alias/, '\1') + @result = @factory.run(Factory::Proxy::AttributesFor, + :test_alias => 'new') + end + + it "should use the passed in value for the alias" do + @result[:test_alias].should == 'new' + end + + it "should discard the predefined value for the attribute" do + @result[:test].should be_nil + end + end + + it "should guess the build class from the factory name" do + @factory.build_class.should == User + end + + it "should create a new factory using the class of the parent" do + child = Factory.new(:child) + child.inherit_from(@factory) + child.build_class.should == @factory.build_class + end + + it "should create a new factory while overriding the parent class" do + child = Factory.new(:child, :class => String) + child.inherit_from(@factory) + child.build_class.should == String + end + + describe "given a parent with attributes" do + before do + @parent_attr = :name + @factory.define_attribute(Factory::Attribute::Static.new(@parent_attr, 'value')) + end + + it "should create a new factory with attributes of the parent" do + child = Factory.new(:child) + child.inherit_from(@factory) + child.attributes.size.should == 1 + child.attributes.first.name.should == @parent_attr + end + + it "should allow a child to define additional attributes" do + child = Factory.new(:child) + child.define_attribute(Factory::Attribute::Static.new(:email, 'value')) + child.inherit_from(@factory) + child.attributes.size.should == 2 + end + + it "should allow to override parent attributes" do + child = Factory.new(:child) + @child_attr = Factory::Attribute::Static.new(@parent_attr, 'value') + child.define_attribute(@child_attr) + child.inherit_from(@factory) + child.attributes.size.should == 1 + child.attributes.first.should == @child_attr + end + end + + it "inherit all callbacks" do + @factory.add_callback(:after_stub) { |object| object.name = 'Stubby' } + child = Factory.new(:child) + child.inherit_from(@factory) + child.attributes.last.should be_kind_of(Factory::Attribute::Callback) + end +end + +describe Factory, "when defined with a custom class" do + before do + @class = Float + @factory = Factory.new(:author, :class => @class) + end + + it "should use the specified class as the build class" do + @factory.build_class.should == @class + end +end + +describe Factory, "when defined with a class instead of a name" do + before do + @class = ArgumentError + @name = :argument_error + @factory = Factory.new(@class) + end + + it "should guess the name from the class" do + @factory.factory_name.should == @name + end + + it "should use the class as the build class" do + @factory.build_class.should == @class + end +end + +describe Factory, "when defined with a custom class name" do + before do + @class = ArgumentError + @factory = Factory.new(:author, :class => :argument_error) + end + + it "should use the specified class as the build class" do + @factory.build_class.should == @class + end +end + +describe Factory, "with a name ending in s" do + include DefinesConstants + + before do + define_constant('Business') + @name = :business + @class = Business + @factory = Factory.new(@name) + end + + it "should have a factory name" do + @factory.factory_name.should == @name + end + + it "should have a build class" do + @factory.build_class.should == @class + end +end + +describe Factory, "with a string for a name" do + before do + @name = :string + @factory = Factory.new(@name.to_s) {} + end + + it "should convert the string to a symbol" do + @factory.factory_name.should == @name + end +end + +describe Factory, "registered with a string name" do + before do + @name = :string + @factory = Factory.new(@name) + Factory.register_factory(@factory) + end + + it "should store the factory using a symbol" do + Factory.factories[@name].should == @factory + end +end + +describe Factory, "for namespaced class" do + include DefinesConstants + + before do + define_constant('Admin') + define_constant('Admin::Settings') + + @name = :settings + @class = Admin::Settings + end + + it "should build namespaced class passed by string" do + factory = Factory.new(@name.to_s, :class => @class.name) + factory.build_class.should == @class + end + + it "should build Admin::Settings class from Admin::Settings string" do + factory = Factory.new(@name.to_s, :class => 'admin/settings') + factory.build_class.should == @class + end +end + describe Factory do include DefinesConstants before do define_constant('User') define_constant('Admin', User) - define_constant('Business') - define_constant('Admin::Settings') end - describe "defining a factory" do + it "should raise an ArgumentError when trying to use a non-existent strategy" do + lambda { + Factory.new(:object, :default_strategy => :nonexistent) {} + }.should raise_error(ArgumentError) + end + + it "should create a new factory with a specified default strategy" do + factory = Factory.new(:object, :default_strategy => :stub) + factory.default_strategy.should == :stub + end + + describe 'defining a child factory without setting default strategy' do before do - @name = :user - @factory = "factory" - stub(@factory).factory_name { @name } - @options = { :class => 'magic' } - stub(Factory).new { @factory } + @parent = Factory.new(:object, :default_strategy => :stub) + @child = Factory.new(:child_object) + @child.inherit_from(@parent) end - after { Factory.factories.clear } - - it "should create a new factory using the specified name and options" do - mock(Factory).new(@name, @options) { @factory } - Factory.define(@name, @options) {|f| } + it "should inherit default strategy from its parent" do + @child.default_strategy.should == :stub end - - it "should pass the factory do the block" do - yielded = nil - Factory.define(@name) do |y| - yielded = y - end - yielded.should == @factory - end - - it "should add the factory to the list of factories" do - Factory.define(@name) {|f| } - @factory.should == Factory.factories[@name] - end - - it "should allow a factory to be found by name" do - Factory.define(@name) {|f| } - Factory.factory_by_name(@name).should == @factory - end - - it "should not allow a duplicate factory definition" do - lambda { - 2.times { Factory.define(@name) {|f| } } - }.should raise_error(Factory::DuplicateDefinitionError) - end - end - describe "a factory" do + describe 'defining a child factory with a default strategy' do before do - @name = :user - @class = User - @factory = Factory.new(@name) + @parent = Factory.new(:object, :default_strategy => :stub) + @child = Factory.new(:child_object2, :default_strategy => :build) + @child.inherit_from(@parent) end - it "should have a factory name" do - @factory.factory_name.should == @name - end - - it "should have a build class" do - @factory.build_class.should == @class - end - - it "should have a default strategy" do - @factory.default_strategy.should == :create - end - - it "should return static attribute when asked for a type" do - result = @factory.type - result.should be_kind_of(Array) - result.first.should be_kind_of(Factory::Attribute::Static) - result.first.name.should == :type - end - - it "should define type as an attribute" do - @factory.type { "it's a type" } - attributes = @factory.attributes - attributes.should be_kind_of(Array) - attributes.size.should == 1 - attributes.first.name.should == :type - end - - it "should return static attribute when asked for the id" do - result = @factory.id - result.should be_kind_of(Array) - result.first.should be_kind_of(Factory::Attribute::Static) - result.first.name.should == :id - end - - it "should define id as an attribute" do - @factory.id { "it's an id" } - attributes = @factory.attributes - attributes.should be_kind_of(Array) - attributes.size.should == 1 - attributes.first.name.should == :id - end - - it "should not allow the same attribute to be added twice" do - lambda { - 2.times { @factory.add_attribute :first_name } - }.should raise_error(Factory::AttributeDefinitionError) - end - - it "should add a static attribute when an attribute is defined with a value" do - attribute = 'attribute' - stub(attribute).name { :name } - mock(Factory::Attribute::Static).new(:name, 'value') { attribute } - @factory.add_attribute(:name, 'value') - end - - it "should add a dynamic attribute when an attribute is defined with a block" do - attribute = 'attribute' - stub(attribute).name { :name } - block = lambda {} - mock(Factory::Attribute::Dynamic).new(:name, block) { attribute } - @factory.add_attribute(:name, &block) - end - - it "should raise for an attribute with a value and a block" do - lambda { - @factory.add_attribute(:name, 'value') {} - }.should raise_error(Factory::AttributeDefinitionError) - end - - describe "adding an attribute using a in-line sequence" do - it "should create the sequence" do - mock(Factory::Sequence).new - @factory.sequence(:name) {} - end - - it "should add a dynamic attribute" do - attribute = 'attribute' - stub(attribute).name { :name } - mock(Factory::Attribute::Dynamic).new(:name, is_a(Proc)) { attribute } - @factory.sequence(:name) {} - @factory.attributes.should include(attribute) - end - end - - describe "adding a callback" do - it "should add a callback attribute when the after_build attribute is defined" do - mock(Factory::Attribute::Callback).new(:after_build, is_a(Proc)) { 'after_build callback' } - @factory.after_build {} - @factory.attributes.should include('after_build callback') - end - - it "should add a callback attribute when the after_create attribute is defined" do - mock(Factory::Attribute::Callback).new(:after_create, is_a(Proc)) { 'after_create callback' } - @factory.after_create {} - @factory.attributes.should include('after_create callback') - end - - it "should add a callback attribute when the after_stub attribute is defined" do - mock(Factory::Attribute::Callback).new(:after_stub, is_a(Proc)) { 'after_stub callback' } - @factory.after_stub {} - @factory.attributes.should include('after_stub callback') - end - - it "should add a callback attribute when defining a callback" do - mock(Factory::Attribute::Callback).new(:after_create, is_a(Proc)) { 'after_create callback' } - @factory.callback(:after_create) {} - @factory.attributes.should include('after_create callback') - end - - it "should raise an InvalidCallbackNameError when defining a callback with an invalid name" do - lambda{ - @factory.callback(:invalid_callback_name) {} - }.should raise_error(Factory::InvalidCallbackNameError) - end - end - - describe "after adding an attribute" do - before do - @attribute = "attribute" - @proxy = "proxy" - - stub(@attribute).name { :name } - stub(@attribute).add_to - stub(@proxy).set - stub(@proxy).result { 'result' } - stub(Factory::Attribute::Static).new { @attribute } - stub(Factory::Proxy::Build).new { @proxy } - - @factory.add_attribute(:name, 'value') - end - - it "should create the right proxy using the build class when running" do - mock(Factory::Proxy::Build).new(@factory.build_class) { @proxy } - @factory.run(Factory::Proxy::Build, {}) - end - - it "should add the attribute to the proxy when running" do - mock(@attribute).add_to(@proxy) - @factory.run(Factory::Proxy::Build, {}) - end - - it "should return the result from the proxy when running" do - mock(@proxy).result() { 'result' } - @factory.run(Factory::Proxy::Build, {}).should == 'result' - end - end - - it "should add an association without a factory name or overrides" do - factory = Factory.new(:post) - name = :user - attr = 'attribute' - mock(Factory::Attribute::Association).new(name, name, {}) { attr } - factory.association(name) - factory.attributes.should include(attr) - end - - it "should return associations" do - factory = Factory.new(:post) - factory.association(:author) - factory.association(:editor) - factory.associations.each do |association| - association.should be_a(Factory::Attribute::Association) - end - factory.associations.size.should == 2 - end - - it "should add an association with overrides" do - factory = Factory.new(:post) - name = :user - attr = 'attribute' - overrides = { :first_name => 'Ben' } - mock(Factory::Attribute::Association).new(name, name, overrides) { attr } - factory.association(name, overrides) - factory.attributes.should include(attr) - end - - it "should add an association with a factory name" do - factory = Factory.new(:post) - attr = 'attribute' - mock(Factory::Attribute::Association).new(:author, :user, {}) { attr } - factory.association(:author, :factory => :user) - factory.attributes.should include(attr) - end - - it "should add an association with a factory name and overrides" do - factory = Factory.new(:post) - attr = 'attribute' - mock(Factory::Attribute::Association).new(:author, :user, :first_name => 'Ben') { attr } - factory.association(:author, :factory => :user, :first_name => 'Ben') - factory.attributes.should include(attr) - end - - it "should raise for a self referencing association" do - factory = Factory.new(:post) - lambda { - factory.association(:parent, :factory => :post) - }.should raise_error(Factory::AssociationDefinitionError) - end - - it "should add an attribute using the method name when passed an undefined method" do - attribute = 'attribute' - stub(attribute).name { :name } - block = lambda {} - mock(Factory::Attribute::Static).new(:name, 'value') { attribute } - @factory.send(:name, 'value') - @factory.attributes.should include(attribute) - end - - it "should allow human_name as a static attribute name" do - attribute = 'attribute' - stub(attribute).name { :name } - mock(Factory::Attribute::Static).new(:human_name, 'value') { attribute} - @factory.human_name 'value' - end - - it "should allow human_name as a dynamic attribute name" do - attribute = 'attribute' - stub(attribute).name { :name } - block = lambda {} - mock(Factory::Attribute::Dynamic).new(:human_name, block) { attribute } - @factory.human_name(&block) - end - - describe "when overriding generated attributes with a hash" do - before do - @attr = :name - @value = 'The price is right!' - @hash = { @attr => @value } - end - - it "should return the overridden value in the generated attributes" do - @factory.add_attribute(@attr, 'The price is wrong, Bob!') - result = @factory.run(Factory::Proxy::AttributesFor, @hash) - result[@attr].should == @value - end - - it "should not call a lazy attribute block for an overridden attribute" do - @factory.add_attribute(@attr) { flunk } - result = @factory.run(Factory::Proxy::AttributesFor, @hash) - end - - it "should override a symbol parameter with a string parameter" do - @factory.add_attribute(@attr, 'The price is wrong, Bob!') - @hash = { @attr.to_s => @value } - result = @factory.run(Factory::Proxy::AttributesFor, @hash) - result[@attr].should == @value - end - end - - describe "overriding an attribute with an alias" do - before do - @factory.add_attribute(:test, 'original') - Factory.alias(/(.*)_alias/, '\1') - @result = @factory.run(Factory::Proxy::AttributesFor, - :test_alias => 'new') - end - - it "should use the passed in value for the alias" do - @result[:test_alias].should == 'new' - end - - it "should discard the predefined value for the attribute" do - @result[:test].should be_nil - end - end - - it "should guess the build class from the factory name" do - @factory.build_class.should == User - end - - describe "when defined with a custom class" do - before do - @class = User - @factory = Factory.new(:author, :class => @class) - end - - it "should use the specified class as the build class" do - @factory.build_class.should == @class - end - end - - describe "when defined with a class instead of a name" do - before do - @class = ArgumentError - @name = :argument_error - @factory = Factory.new(@class) - end - - it "should guess the name from the class" do - @factory.factory_name.should == @name - end - - it "should use the class as the build class" do - @factory.build_class.should == @class - end - end - - describe "when defined with a custom class name" do - before do - @class = ArgumentError - @factory = Factory.new(:author, :class => :argument_error) - end - - it "should use the specified class as the build class" do - @factory.build_class.should == @class - end + it "should override the default strategy from parent" do + @child.default_strategy.should == :build end end - describe "a factory with a name ending in s" do - before do - @name = :business - @class = Business - @factory = Factory.new(@name) - end - - it "should have a factory name" do - @factory.factory_name.should == @name - end - - it "should have a build class" do - @factory.build_class.should == @class - end - end - - describe "a factory with a string for a name" do - before do - @name = :user - @factory = Factory.new(@name.to_s) {} - end - - it "should convert the string to a symbol" do - @factory.factory_name.should == @name - end - end - - describe "a factory defined with a string name" do - before do - Factory.factories = {} - @name = :user - @factory = Factory.define(@name.to_s) {} - end - - it "should store the factory using a symbol" do - Factory.factories[@name].should == @factory - end - end - - describe "a factory for namespaced class" do - before do - Factory.factories = {} - @name = :settings - @class = Admin::Settings - end - - it "should build namespaced class passed by string" do - factory = Factory.define(@name.to_s, :class => @class.name) {} - factory.build_class.should == @class - end - - it "should build Admin::Settings class from Admin::Settings string" do - factory = Factory.define(@name.to_s, :class => 'admin/settings') {} - factory.build_class.should == @class - end - end - - describe "after defining a factory" do - before do - @name = :user - @factory = "factory" - - Factory.factories[@name] = @factory - end - - after { Factory.factories.clear } - - it "should use Proxy::AttributesFor for Factory.attributes_for" do - mock(@factory).run(Factory::Proxy::AttributesFor, :attr => 'value') { 'result' } - Factory.attributes_for(@name, :attr => 'value').should == 'result' - end - - it "should use Proxy::Build for Factory.build" do - mock(@factory).run(Factory::Proxy::Build, :attr => 'value') { 'result' } - Factory.build(@name, :attr => 'value').should == 'result' - end - - it "should use Proxy::Create for Factory.create" do - mock(@factory).run(Factory::Proxy::Create, :attr => 'value') { 'result' } - Factory.create(@name, :attr => 'value').should == 'result' - end - - it "should use Proxy::Stub for Factory.stub" do - mock(@factory).run(Factory::Proxy::Stub, :attr => 'value') { 'result' } - Factory.stub(@name, :attr => 'value').should == 'result' - end - - it "should use default strategy option as Factory.default_strategy" do - stub(@factory).default_strategy { :create } - mock(@factory).run(Factory::Proxy::Create, :attr => 'value') { 'result' } - Factory.default_strategy(@name, :attr => 'value').should == 'result' - end - - it "should use the default strategy for the global Factory method" do - stub(@factory).default_strategy { :create } - mock(@factory).run(Factory::Proxy::Create, :attr => 'value') { 'result' } - Factory(@name, :attr => 'value').should == 'result' - end - - [:build, :create, :attributes_for, :stub].each do |method| - it "should raise an ArgumentError on #{method} with a nonexistant factory" do - lambda { Factory.send(method, :bogus) }.should raise_error(ArgumentError) - end - - it "should recognize either 'name' or :name for Factory.#{method}" do - stub(@factory).run - lambda { Factory.send(method, @name.to_s) }.should_not raise_error - lambda { Factory.send(method, @name.to_sym) }.should_not raise_error - end - end - end - - describe 'defining a factory with a parent parameter' do - before do - @parent = Factory.define :object do |f| - f.name 'Name' - end - end - - after { Factory.factories.clear } - - it "should raise an ArgumentError when trying to use a non-existent factory as parent" do - lambda { - Factory.define(:child, :parent => :nonexsitent) {} - }.should raise_error(ArgumentError) - end - - it "should create a new factory using the class of the parent" do - child = Factory.define(:child, :parent => :object) {} - child.build_class.should == @parent.build_class - end - - it "should create a new factory while overriding the parent class" do - class Other; end - - child = Factory.define(:child, :parent => :object, :class => Other) {} - child.build_class.should == Other - end - - it "should create a new factory with attributes of the parent" do - child = Factory.define(:child, :parent => :object) {} - child.attributes.size.should == 1 - child.attributes.first.name.should == :name - end - - it "should allow to define additional attributes" do - child = Factory.define(:child, :parent => :object) do |f| - f.email 'person@somebody.com' - end - child.attributes.size.should == 2 - end - - it "should allow to override parent attributes" do - child = Factory.define(:child, :parent => :object) do |f| - f.name { 'Child Name' } - end - child.attributes.size.should == 1 - child.attributes.first.should be_kind_of(Factory::Attribute::Dynamic) - end - - it "inherit all callbacks" do - Factory.define(:child, :parent => :object) do |f| - f.after_stub {|o| o.name = 'Stubby' } - end - - grandchild = Factory.define(:grandchild, :parent => :child) do |f| - f.after_stub {|o| o.name = "#{o.name} McStubby" } - end - - grandchild.attributes.size.should == 3 - grandchild.attributes.first.should be_kind_of(Factory::Attribute::Callback) - grandchild.attributes[1].should be_kind_of(Factory::Attribute::Callback) - end - end - - describe 'defining a factory with a default strategy parameter' do - it "should raise an ArgumentError when trying to use a non-existent factory" do - lambda { - Factory.define(:object, :default_strategy => :nonexistent) {} - }.should raise_error(ArgumentError) - end - - it "should create a new factory with a specified default strategy" do - factory = Factory.define(:object, :default_strategy => :stub) {} - factory.default_strategy.should == :stub - end - - describe 'defining a child factory without setting default strategy' do - before do - @child = Factory.define(:child_object, :parent => :object) {} - end - - it "should inherit default strategy from its parent" do - @child.default_strategy.should == :stub - end - end - - describe 'defining a child factory with a default strategy' do - before do - @child2 = Factory.define(:child_object2, :parent => :object, :default_strategy => :build) {} - end - - it "should not inherit default strategy from parent" do - @child2.default_strategy.should == :build - end - end - end +end +describe "definition loading" do def self.in_directory_with_files(*files) before do @pwd = Dir.pwd @@ -656,5 +436,4 @@ describe Factory do factory = Factory.new(:name_with_underscores) factory.human_name.should == 'name with underscores' end - end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 68f1a1f..88873f5 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -10,6 +10,10 @@ require 'factory_girl' Spec::Runner.configure do |config| config.mock_with RR::Adapters::Rspec + config.after do + Factory.factories.clear + Factory.sequences.clear + end end share_as :DefinesConstants do