0

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?

Noah Clark
  • 8,101
  • 14
  • 74
  • 116

1 Answers1

1

The short answer - yes, you do create objects.

The long answer:

  1. 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
    
  2. In controller: You does not check if PeriodRegistration model saved or not.

  3. 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
    
  4. When testing controller you can use mock object instead of real model.

Mikhail Vaysman
  • 412
  • 3
  • 10
  • In regard to your #1, That doesn't work. I tested it in the console, and I need to do 'pr.period.event' to get the event. – Noah Clark Sep 01 '12 at 20:09
  • Your #3 helped me on another issue I was having though! – Noah Clark Sep 01 '12 at 20:23
  • @NoahClark About #1. You must create new method in PeriodRegistration model. I have updated my answer. – Mikhail Vaysman Sep 01 '12 at 22:29
  • ah, that makes sense. Is it common for rails developers to do that? It seems, uh, heavy handed? – Noah Clark Sep 02 '12 at 00:28
  • @NoahClark It is common for OO language. It needs to create loosely coupled system. Do you read about [The Law of Demeter](http://en.wikipedia.org/wiki/Law_of_Demeter)? – Mikhail Vaysman Sep 02 '12 at 00:59
  • Yeah, I've read that. I'm still not convinced. I've posted up on http://stackoverflow.com/questions/12237431/the-law-of-demeter to get a sense of what the community thinks. Still would love for you to weigh in. – Noah Clark Sep 02 '12 at 15:58