Reputation: 8131
My test looks like this:
def setup
@period_registration= FactoryGirl.create(:period_registration)
end
test "should post save_period" do
sign_in(FactoryGirl.create(:user))
assert_difference('PeriodRegistration.count') do
post :save_period, period_registration: FactoryGirl.attributes_for(:period_registration)
end
assert_not_nil assigns(:period_registration)
end
But when I run it, I get this error:
1) Error:
test_should_post_save_period(PeriodRegistrationsControllerTest):
NoMethodError: undefined method `event' for nil:NilClass
Here is my controller:
def save_period
@period_registration = PeriodRegistration.new(params[:registration])
@period_registration.save
flash[:success] = "Successfully Registered for Session."
redirect_to event_url(@period_registration.period.event)
end
My factories look like this:
factory :event do
name 'First Event'
street '123 street'
city 'Chicago'
state 'Iowa'
date Date.today
end
factory :period do
name 'First Period'
description 'This is a description'
start_time Time.now + 10.days
end_time Time.now + 10.days + 2.hours
event
product
end
factory :period_registration do
user
period
end
Do I need to create a period object and an event object? If so how? I don't think this is the issue because, I believe by having "period" and then "product" and then "event" in the various factories automatically creates these.
Any ideas on where to look from here?
Upvotes: 0
Views: 84
Reputation: 412
The short answer - yes, you do create objects.
The long answer:
In controller:
@period_registration.period.event
This line of code violate The Law Of Demeter. This is not good design. This line of code should looks like:
@period_registration.event
But you must create new method in PeriodRegistration model. The simplest variant of method can be:
def event
period.event
end
In controller: You does not check if PeriodRegistration model saved or not.
As I understand PeriodRegistration model have 2 associations and when you use FactoryGirl.attributes_for, the factory does not create associated objects, it just give you set of attributes for PeriodRegistration. To make this test pass you should create these 2 objects befor you call controller. Aslo the best practice is - test should have only one assertion. For example:
def setup
@user = FactoryGirl.create(:user)
@period = FactoryGirl.create(:period)
end
test "should post save_period" do
sign_in(@user)
assert_difference('PeriodRegistration.count') do
post :save_period, period_registration: FactoryGirl.attributes_for(:period_registration, user: @user, period: @period)
end
end
test "should assings @period_registration" do
sign_in(@user)
post :save_period, period_registration: FactoryGirl.attributes_for(:period_registration, user: @user, period: @period)
assert_not_nil assigns(:period_registration)
end
When testing controller you can use mock object instead of real model.
Upvotes: 1