Skip to content

Commit

Permalink
Refactored Factory#stub so it uses a real instance and throws excepti…
Browse files Browse the repository at this point in the history
…ons when connections to the database are triggered.
  • Loading branch information
qrush committed Apr 28, 2009
1 parent 263e7be commit 4ecd2f1
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 48 deletions.
45 changes: 33 additions & 12 deletions lib/factory_girl/proxy/stub.rb
Original file line number Diff line number Diff line change
@@ -1,27 +1,48 @@
class Factory
class Proxy
class Stub < Proxy #:nodoc:
@@next_id = 1000

def initialize(klass)
@mock = Object.new
@stub = klass.new
@stub.id = next_id
@stub.instance_eval do
def new_record?
id.nil?
end

def connection
raise "stubbed models are not allowed to access the database"
end

def reload
raise "stubbed models are not allowed to access the database"
end
end
end

def next_id
@@next_id += 1
end

def get(attribute)
@mock.send(attribute)
@stub.send(attribute)
end

def set(attribute, value)
unless @mock.respond_to?("#{attribute}=")
class << @mock; self end.send(:attr_accessor, attribute)
end
@mock.send("#{attribute}=", value)
@stub.send(:"#{attribute}=", value)
end

def associate(name, factory, attributes)
set(name, nil)
set(name, Factory.stub(factory, attributes))
end

def association(factory, overrides = {})
Factory.stub(factory, overrides)
end

def result
@mock
@stub
end
end
end
Expand Down
76 changes: 45 additions & 31 deletions spec/factory_girl/proxy/stub_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,54 +2,68 @@

describe Factory::Proxy::Stub do
before do
@proxy = Factory::Proxy::Stub.new(@class)
@class = "class"
@instance = "instance"
stub(@class).new { @instance }
stub(@instance, :id=)
stub(@instance).id { 42 }
stub(@instance).reload { @instance.connection.reload }

@stub = Factory::Proxy::Stub.new(@class)
end

it "should not be a new record" do
@stub.result.should_not be_new_record
end

it "should not be able to connect to the database" do
lambda { @stub.result.reload }.should raise_error(RuntimeError)
end

describe "when asked to associate with another factory" do
describe "when a user factory exists" do
before do
stub(Factory).create
@proxy.associate(:owner, :user, {})
@user = "user"
stub(Factory).stub(:user, {}) { @user }
end

it "should not set a value for the association" do
@proxy.result.owner.should be_nil
end
end
describe "when asked to associate with another factory" do
before do
stub(@instance).owner { @user }
mock(Factory).stub(:user, {}) { @user }
mock(@stub).set(:owner, @user)

it "should return nil when building an association" do
@proxy.association(:user).should be_nil
end
@stub.associate(:owner, :user, {})
end

it "should not call Factory.create when building an association" do
mock(Factory).create.never
@proxy.association(:user).should be_nil
end
it "should set a value for the association" do
@stub.result.owner.should == @user
end
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 the association when building one" do
mock(Factory).create.never
@stub.association(:user).should == @user
end

it "should return a mock object when asked for the result" do
@proxy.result.should be_kind_of(Object)
it "should return the actual instance when asked for the result" do
@stub.result.should == @instance
end
end

describe "after setting an attribute" do
describe "with an existing attribute" do
before do
@proxy.set(:attribute, 'value')
@value = "value"
mock(@instance).send(:attribute) { @value }
mock(@instance).send(:attribute=, @value)
@stub.set(:attribute, @value)
end

it "should add a stub to the resulting object" do
@proxy.attribute.should == 'value'
it "should to the resulting object" do
@stub.attribute.should == 'value'
end

it "should return that value when asked for that attribute" do
@proxy.get(:attribute).should == 'value'
@stub.get(:attribute).should == @value
end
end

it "should define a setter even if attribute= is defined" do
@proxy.set('attribute', nil)
lambda { @proxy.set('age', 18) }.should_not raise_error
end
end
31 changes: 26 additions & 5 deletions spec/integration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@

end

describe "a generated mock instance" do
describe "a generated stub instance" do

before do
@stub = Factory.stub(:user, :first_name => 'Bill')
Expand All @@ -122,18 +122,39 @@
end
end

it "should correctly assign lazy, dependent attributes" do
it "should correctly assign attributes" do
@stub.email.should == "bill.hendrix@example.com"
end

it "should override attrbutes" do
it "should override attributes" do
@stub.first_name.should == 'Bill'
end

it "should not assign associations" do
Factory.stub(:post).author.should be_nil
it "should assign associations" do
Factory.stub(:post).author.should_not be_nil
end

it "should have an id" do
@stub.id.should > 0
end

it "should have unique IDs" do
@other_stub = Factory.stub(:user)
@stub.id.should_not == @other_stub.id
end

it "should not be considered a new record" do
@stub.should_not be_new_record
end

it "should raise exception if connection to the database is attempted" do
lambda { @stub.connection }.should raise_error(RuntimeError)
lambda { @stub.update_attribute(:first_name, "Nick") }.should raise_error(RuntimeError)
lambda { @stub.reload }.should raise_error(RuntimeError)
lambda { @stub.destroy }.should raise_error(RuntimeError)
lambda { @stub.save }.should raise_error(RuntimeError)
lambda { @stub.increment!(:age) }.should raise_error(RuntimeError)
end
end

describe "an instance generated by a factory with a custom class name" do
Expand Down

0 comments on commit 4ecd2f1

Please sign in to comment.