Reputation: 191
I guess the problem is that I do not know how to use factory girl with Rspec correctly. Or testing in rails correctly for that matter. Still think it is a bit weird though..
I have a class, User, with the following factory:
FactoryGirl.define do
factory :user do
name "admin"
email "[email protected]"
adminstatus "1"
password "foobar"
password_confirmation "foobar"
end
factory :user_no_admin, class: User do
name "user"
email "[email protected]"
adminstatus "2"
password "foobar"
password_confirmation "foobar"
end
...
My test looks like this:
...
describe "signin as admin user" do
before { visit login_path }
describe "with valid information" do
let(:user_no_admin) { FactoryGirl.create(:user_no_admin) }
let(:user) { FactoryGirl.create(:user) }
before do
fill_in "User", with: user.name
fill_in "Password", with: user.password
click_button "Login"
end
it "should list users if user is admin" do
response.should have_selector('th', content: 'Name')
response.should have_selector('td', content: user_no_admin.name)
response.should have_selector('td', content: user.name)
end
end
end#signin as admin user
...
Basically I am trying to test that if you log in as an admin, you should see a list of all the users. I have a test for logging on as a non-admin later on in the file. I have a couple of users in the db already.
In the list of users 'admin' that logged in is displayed along with the users already in the db. 'user' is however not displayed unless I do something like this before:
fill_in "User", with: user_no_admin.name
fill_in "Password", with: user_no_admin.password
It is as if it won't exist unless I use it. However, if I use a puts it does print the information I am putting, even if I do not do the 'fill_in' above.
I have a similar example where a puts helps me.
describe "should have company name" do
let(:company) { FactoryGirl.create(:company) }
let(:category) { FactoryGirl.create(:category) }
let(:company_category) { FactoryGirl.create(:company_category, company_id: company.id, category_id: category.id) }
it "should contain companies name" do
puts company_category.category_id
get 'categories/' + company.categories[0].id.to_s
response.should have_selector('h4', :content => company.name)
end
end
Without the puts above I get a
Called id for nil
Do I have to initiate(?) an object created by Factory girl before I can use it in some way?
Any other code needed?
Upvotes: 3
Views: 3592
Reputation: 1413
Try to use trait in the factory girl,there is an example as mentioned in the this link
Upvotes: -1
Reputation: 234
I had a similar issue with an existing test I broke, with a slightly different cause that was interesting.
In this case, the controller under test was originally calling save
, but I changed it to call save!
, and updated the test accordingly.
The revised test was:
let
statementexpect_any_instance_of(MyObject).to receive(:save!)
) Internally, it would appear that FactoryGirl was calling the save!
method, and after changing the expectation from save to save!, no work was actually done (and the code under test couldn't find the instance from the DB)
that I needed to update and had a hard time getting to actually pass without a hack)
Upvotes: 1
Reputation: 212
Instead of:
factory :user do
name "admin"
email "[email protected]"
...
I will do:
factory :user do |f|
f.name "admin"
f.email "[email protected]"
...
Instead of:
let(:user_no_admin) { FactoryGirl.create(:user_no_admin) }
let(:user) { FactoryGirl.create(:user) }
I will do:
@user_no_admin = Factory(:user_no_admin)
@user = Factory(:user)
Upvotes: 1
Reputation: 734
let(:whatever)
Is not creating the objects until the first time you call them. If you want it to be available before first use, use
let!(:whatever)
instead.
Or use a before block:
before(:each) do
@company = FactoryGirl.create(:company)
....
end
Which will create the objects before you need to use them.
Upvotes: 9