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

Clean up proxy specs with shared examples

This commit is contained in:
Joshua Clayton 2011-08-16 23:08:24 -04:00
parent 0b2c4da0a4
commit d296a22586
7 changed files with 161 additions and 271 deletions

View file

@ -7,7 +7,6 @@ module FactoryGirl
end
def get(attribute)
nil
end
def set(attribute, value)
@ -63,7 +62,6 @@ module FactoryGirl
# FactoryGirl.create(:post)
#
def association(name, overrides = {})
nil
end
def method_missing(method, *args, &block)

View file

@ -1,51 +1,42 @@
require 'spec_helper'
describe FactoryGirl::Proxy::AttributesFor do
before do
@proxy = FactoryGirl::Proxy::AttributesFor.new(@class)
let(:proxy_class) { stub("class") }
subject { FactoryGirl::Proxy::AttributesFor.new(proxy_class) }
it_should_behave_like "proxy without association support"
it "returns a hash when asked for the result" do
subject.result(nil).should be_kind_of(Hash)
end
describe "when asked to associate with another factory" do
before do
FactoryGirl.stubs(:create)
@proxy.associate(:owner, :user, {})
context "after associating a factory" do
let(:attribute) { :owner }
before { subject.associate(attribute, :user, {}) }
it "doesn't set that key in the resulting hash" do
subject.result(nil).should_not have_key(attribute)
end
it "should not set a value for the association" do
(@proxy.result(nil).key?(:owner)).should_not be
it "returns nil when asked for that attribute" do
subject.get(attribute).should be_nil
end
end
it "should return nil when building an association" do
@proxy.association(:user).should be_nil
end
it "should not call Factory.create when building an association" do
FactoryGirl.stubs(:create)
@proxy.association(:user).should be_nil
FactoryGirl.should have_received(:create).never
end
it "should always return nil when building an association" do
@proxy.set(:association, 'x')
@proxy.association(:user).should be_nil
end
it "should return a hash when asked for the result" do
@proxy.result(nil).should be_kind_of(Hash)
end
describe "after setting an attribute" do
before do
@proxy.set(:attribute, 'value')
let(:attribute) { :attribute }
let(:value) { "value" }
before { subject.set(attribute, value) }
it "sets that value in the resulting hash" do
subject.result(nil)[attribute].should == value
end
it "should set that value in the resulting hash" do
@proxy.result(nil)[:attribute].should == 'value'
end
it "should return that value when asked for that attribute" do
@proxy.get(:attribute).should == 'value'
it "returns that value when asked for that attribute" do
subject.get(attribute).should == value
end
end
end

View file

@ -1,77 +1,12 @@
require 'spec_helper'
describe FactoryGirl::Proxy::Build do
before do
@instance = stub("built-instance", :attribute => "value", :attribute= => nil, :owner= => nil)
@class = stub("class", :new => @instance)
@proxy = FactoryGirl::Proxy::Build.new(@class)
end
let(:instance) { stub("built-instance") }
let(:proxy_class) { stub("class", :new => instance) }
it "should instantiate the class" do
@class.should have_received(:new)
end
subject { FactoryGirl::Proxy::Build.new(proxy_class) }
describe "when asked to associate with another factory" do
before do
@association = "associated-instance"
@associated_factory = stub("associated-factory", :run => @association)
FactoryGirl.stubs(:factory_by_name => @associated_factory)
@overrides = { 'attr' => 'value' }
@proxy.associate(:owner, :user, @overrides)
end
it "should create the associated instance" do
@associated_factory.should have_received(:run).with(FactoryGirl::Proxy::Create, @overrides)
end
it "should set the associated instance" do
@instance.should have_received(:owner=).with(@association)
end
end
it "should run create when building an association" do
association = "associated-instance"
associated_factory = stub("associated-factory", :run => association)
FactoryGirl.stubs(:factory_by_name => associated_factory)
overrides = { 'attr' => 'value' }
@proxy.association(:user, overrides).should == association
associated_factory.should have_received(:run).with(FactoryGirl::Proxy::Create, overrides)
end
it "should return the built instance when asked for the result" do
@proxy.result(nil).should == @instance
end
it "should run the :after_build callback when retrieving the result" do
thing_to_call = stub("object", :foo => nil)
@proxy.add_callback(:after_build, proc{ thing_to_call.foo })
@proxy.result(nil)
thing_to_call.should have_received(:foo)
end
describe "when setting an attribute" do
before do
@instance.stubs(:attributes=)
@proxy.set(:attribute, 'value')
end
it "should set that value" do
@instance.should have_received(:attribute=).with('value')
end
end
describe "when getting an attribute" do
before do
@result = @proxy.get(:attribute)
end
it "should ask the built class for the value" do
@instance.should have_received(:attribute)
end
it "should return the value for that attribute" do
@result.should == 'value'
end
end
it_should_behave_like "proxy with association support", FactoryGirl::Proxy::Create
it_should_behave_like "proxy with standard getters and setters", :attribute_name, "attribute value!"
it_should_behave_like "proxy with callbacks", :after_build
end

View file

@ -1,95 +1,42 @@
require 'spec_helper'
describe FactoryGirl::Proxy::Create do
before do
@instance = stub("built-instance", :attribute => "value", :attribute= => nil, :owner= => nil, :save! => nil)
@class = stub("class", :new => @instance)
@proxy = FactoryGirl::Proxy::Create.new(@class)
end
it "should instantiate the class" do
@class.should have_received(:new)
end
let(:instance) { stub("created-instance", :save! => true) }
let(:proxy_class) { stub("class", :new => instance) }
describe "when asked to associate with another factory" do
before do
@association = "associated-instance"
@associated_factory = stub("associated-factory", :run => @association)
FactoryGirl.stubs(:factory_by_name => @associated_factory)
@overrides = { 'attr' => 'value' }
@proxy.associate(:owner, :user, @overrides)
end
subject { FactoryGirl::Proxy::Create.new(proxy_class) }
it "should create the associated instance" do
@associated_factory.should have_received(:run).with(FactoryGirl::Proxy::Create, @overrides)
end
it_should_behave_like "proxy with association support", FactoryGirl::Proxy::Create
it_should_behave_like "proxy with standard getters and setters", :attribute_name, "attribute value!"
it_should_behave_like "proxy with callbacks", :after_build
it_should_behave_like "proxy with callbacks", :after_create
it "should set the associated instance" do
@instance.should have_received(:owner=).with(@association)
end
end
it "should run create when building an association" do
association = "associated-instance"
associated_factory = stub("associated-factory", :run => association)
FactoryGirl.stubs(:factory_by_name => associated_factory)
overrides = { 'attr' => 'value' }
@proxy.association(:user, overrides).should == association
associated_factory.should have_received(:run).with(FactoryGirl::Proxy::Create, overrides)
end
describe "when asked for the result" do
before do
@build_spy = stub("build", :foo => nil)
@create_spy = stub("create", :foo => nil)
@proxy.add_callback(:after_build, proc{ @build_spy.foo })
@proxy.add_callback(:after_create, proc{ @create_spy.foo })
@result = @proxy.result(nil)
end
it "should save the instance" do
@instance.should have_received(:save!)
end
it "should return the built instance" do
@result.should == @instance
end
it "should run both the build and the create callbacks" do
@build_spy.should have_received(:foo)
@create_spy.should have_received(:foo)
end
it "saves the instance before returning the result" do
subject.result(nil)
instance.should have_received(:save!)
end
it "runs a custom create block" do
block = stub('custom create block', :call => nil)
@instance.stubs(:save!).raises(RuntimeError)
instance = @proxy.result(block)
subject.result(block)
block.should have_received(:call).with(instance)
instance.should have_received(:save!).never
end
describe "when setting an attribute" do
before do
@proxy.set(:attribute, 'value')
end
context "callback execution order" do
let(:after_build_callback) { stub("after_build callback", :foo => nil) }
let(:after_create_callback) { stub("after_create callback", :foo => nil) }
let(:callback_sequence) { sequence("after_* callbacks") }
it "should set that value" do
@instance.should have_received(:attribute=).with('value')
end
end
it "runs after_build callbacks before after_create callbacks" do
subject.add_callback(:after_build, proc { after_build_callback.foo })
subject.add_callback(:after_create, proc { after_create_callback.foo })
describe "when getting an attribute" do
before do
@result = @proxy.get(:attribute)
end
after_build_callback.expects(:foo).once.in_sequence(callback_sequence)
after_create_callback.expects(:foo).once.in_sequence(callback_sequence)
it "should ask the built class for the value" do
@instance.should have_received(:attribute)
end
it "should return the value for that attribute" do
@result.should == 'value'
subject.result(nil)
end
end
end

View file

@ -1,95 +1,25 @@
require 'spec_helper'
describe FactoryGirl::Proxy::Stub do
before do
@instance = stub("instance", :id= => nil, :id => 42)
@class = stub("class", :new => @instance)
let(:instance) { stub("instance", :id= => nil, :id => 42) }
let(:proxy_class) { stub("class", :new => instance) }
@stub = FactoryGirl::Proxy::Stub.new(@class)
end
subject { FactoryGirl::Proxy::Stub.new(proxy_class) }
it "should not be a new record" do
@stub.result(nil).should_not be_new_record
end
it_should_behave_like "proxy with association support", FactoryGirl::Proxy::Stub
it_should_behave_like "proxy with standard getters and setters", :attribute_name, "attribute value!"
it_should_behave_like "proxy with callbacks", :after_stub
it "should be persisted" do
@stub.result(nil).should be_persisted
end
context "asking for a result" do
it { subject.result(nil).should_not be_new_record }
it { subject.result(nil).should be_persisted }
it "should not be able to connect to the database" do
lambda { @stub.result(nil).reload }.should raise_error(RuntimeError)
end
describe "when a user factory exists" do
before do
@user = "user"
@associated_factory = stub('associate-factory')
FactoryGirl.stubs(:factory_by_name => @associated_factory)
end
describe "when asked to associate with another factory" do
before do
@instance.stubs(:owner => @user)
@associated_factory.stubs(:run => @user)
@stub.stubs(:set)
@stub.associate(:owner, :user, {})
[:save, :destroy, :connection, :reload, :update_attribute].each do |database_method|
it "raises when attempting to connect to the database by calling #{database_method}" do
expect do
subject.result(nil).send(database_method)
end.to raise_error(RuntimeError, "stubbed models are not allowed to access the database")
end
it "should set a value for the association" do
@stub.result(nil).owner.should == @user
end
it "should set the owner as the user" do
@stub.should have_received(:set).with(:owner, @user)
end
it "should create a stub correctly on the association" do
@associated_factory.should have_received(:run).with(FactoryGirl::Proxy::Stub, {})
end
end
it "should return the association when building one" do
@associated_factory.stubs(:run => @user)
@stub.association(:user).should == @user
@associated_factory.should have_received(:run).with(FactoryGirl::Proxy::Stub, {})
end
describe "when asked for the result" do
it "should return the actual instance" do
@stub.result(nil).should == @instance
end
it "should run the :after_stub callback" do
@spy = stub("after_stub callback", :foo => nil)
@stub.add_callback(:after_stub, proc{ @spy.foo })
@stub.result(nil)
@spy.should have_received(:foo)
end
end
end
describe "with an existing attribute" do
before do
@value = "value"
@instance.stubs(:attribute => @value, :attribute= => @value)
@stub.set(:attribute, @value)
end
it "should to the resulting object" do
@stub.attribute.should == 'value'
end
it "should set the attribute as the value" do
@instance.should have_received(:attribute=).with(@value)
end
it "should retrieve the attribute" do
@stub.attribute
@instance.should have_received(:attribute)
end
it "should return that value when asked for that attribute" do
@stub.get(:attribute).should == @value
end
end
end

View file

@ -3,6 +3,8 @@ require 'spec_helper'
describe FactoryGirl::Proxy do
subject { FactoryGirl::Proxy.new(Class.new) }
it_should_behave_like "proxy without association support"
it "doesn't raise when assigning a value to an attribute" do
expect { subject.set(:name, "a name") }.to_not raise_error
end
@ -16,10 +18,6 @@ describe FactoryGirl::Proxy do
subject.name.should == "it's a name"
end
it "doesn't raise when asked to associate with another factory" do
expect { subject.associate(:owner, :user, {}) }.to_not raise_error
end
it "raises an error when asking for the result" do
expect { subject.result(nil) }.to raise_error(NotImplementedError)
end

View file

@ -0,0 +1,91 @@
shared_examples_for "proxy without association support" do
it "doesn't raise when asked to associate with another factory" do
expect { subject.associate(:owner, :user, {}) }.to_not raise_error
end
it "does not call FactoryGirl.create when building an association" do
FactoryGirl.stubs(:create)
subject.association(:user)
FactoryGirl.should have_received(:create).never
end
it "returns nil when building an association" do
subject.set(:association, 'x')
subject.association(:user).should be_nil
end
end
shared_examples_for "proxy with association support" do |factory_girl_proxy_class|
let(:factory_name) { :user }
let(:association_name) { :owner }
let(:factory) { stub("associate_factory") }
let(:overrides) { { :one => 1, :two => 2 } }
before do
FactoryGirl.stubs(:factory_by_name => factory)
instance.stubs(association_name => factory_name)
factory.stubs(:run => factory_name)
subject.stubs(:set)
end
it "sets a value for the association" do
subject.associate(association_name, factory_name, {})
subject.result(nil).send(association_name).should == factory_name
end
it "sets the association attribute as the factory" do
subject.associate(association_name, factory_name, {})
subject.should have_received(:set).with(association_name, factory_name)
end
it "runs the factory with the correct proxy class" do
subject.associate(association_name, factory_name, {})
factory.should have_received(:run).with(factory_girl_proxy_class, {})
end
it "runs the factory with the correct proxy class and overrides" do
subject.associate(association_name, factory_name, overrides)
factory.should have_received(:run).with(factory_girl_proxy_class, overrides)
end
end
shared_examples_for "proxy with standard getters and setters" do |attribute, value|
before do
instance.stubs(:"#{attribute}=" => value, :"#{attribute}" => value)
end
describe "when setting an attribute" do
before do
subject.set(attribute, value)
end
its(attribute) { should == value }
it { instance.should have_received(:"#{attribute}=").with(value) }
end
describe "when getting an attribute" do
it { subject.get(attribute).should == value }
it "retrieves the value from the instance" do
subject.get(attribute)
instance.should have_received(:"#{attribute}")
end
end
end
shared_examples_for "proxy with callbacks" do |callback_name|
let(:callback) { stub("#{callback_name} callback", :foo => nil) }
before do
subject.add_callback(callback_name, proc { callback.foo })
end
it "runs the #{callback_name} callback" do
subject.result(nil)
callback.should have_received(:foo).once
end
it "returns the proxy instance" do
subject.result(nil).should == instance
end
end