Say I have models User
and Post
, a user has_many
posts and a post belongs_to
a user.
When I write a spec for Post
, my first instinct is to write something like this:
before do
@user = FactoryGirl.create :user
@post = @user.posts.new(title: "Foo", content: "bar)
end
... tests for @post go here ...
But this is going to create a new User - hitting the database - for every single test, which is going to slow things down. Is there a better way to do this that will speed my tests up and avoid hitting the DB so often?
As I understand it, I can't use FactoryGirl.build :user
because, even though it won't hit the DB, the associations won't work properly because @user
won't have an ID and so @post.user
won't work (it returns nil
.)
I could use FactoryGirl.build_stubbed :user
which created a "fake persisted" @user
which does have an ID, but @post.user
still returns nil. Does build_stubbed
have any practical advantage over build
when I'm testing things related to associations?
I suppose I could use build_stubbed
stub @post.user
so it returns @user
... is there any reason this might be a bad idea?
Or should I just use create
and accept the speed hit?
The only other alternative I can think of would be to set up @user in a before(:all)
block which seems like a bad idea.
What's the best way to write these kind of tests in a clean, concise way that avoids making too many DB queries?
If you don't want your tests to be hitting the database, this is what you would have to do.
before do
@user = FactoryGirl.build_stubbed :user
@post = FactoryGirl.build_stubbed :post
@user.stub(:posts).and_return([@post])
@post.stub(:user).and_return(@user)
end
Note: Be careful when using before(:all)
. It doesn't get executed in a transaction. So whatever you create in before(:all)
will get left behind in the database and might cause conflict with other tests
About FactoryGirl.build
, it builds the object, but creates the associations.
For eg:
factory :user do
association posts
end
FactoryGirl.build(:user) #this creates posts in the database even though you are only building the parent object(user)
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments