Search code examples
ruby-on-railsrubyfunctional-testing

Ruby on Rails: related models functional test error


I have been trying to figure out what is wrong with my test. First, it works in the console.

The console:

1.9.2-p290 :015 >   a = Allergy.all
  Allergy Load (0.4ms)  SELECT "allergies".* FROM "allergies" 
 => [#<Allergy id: 1, name: "Milk", desc: "Allergic to milk", created_at: "2012-01-08 16:38:55", updated_at: "2012-01-09 11:48:20", patient_id: 1>, #<Allergy id: 2, name: "Blah", desc: "Test", created_at: "2012-01-09 12:20:48", updated_at: "2012-01-09 12:20:48", patient_id: 2>] 
1.9.2-p290 :016 > a[0]
 => #<Allergy id: 1, name: "Milk", desc: "Allergic to milk", created_at: "2012-01-08 16:38:55", updated_at: "2012-01-09 11:48:20", patient_id: 1> 
1.9.2-p290 :017 > a[0].patient.full_name
  Patient Load (0.5ms)  SELECT "patients".* FROM "patients" WHERE "patients"."id" = 1 LIMIT 1
 => "Test Full Name" 
1.9.2-p290 :018 >

Allergy Controller

class AllergiesController < ApplicationController
  # GET /allergies
  # GET /allergies.json
  def index
    @allergies = Allergy.all

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @allergies }
    end
  end

  # GET /allergies/1
  # GET /allergies/1.json
  def show
    @allergy = Allergy.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @allergy }
    end
  end
  ...

Allergy Model

class Allergy < ActiveRecord::Base
  validates :name, :presence => true
  belongs_to :patient
end

Patient Model

class Patient < ActiveRecord::Base
  validates :first_name, :last_name, :dob, :presence => true
  has_many :allergies

  def age
    now = Time.now.utc.to_date
    now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
  end

  def full_name
    first_name
  end
end

The test:

require 'test_helper'

class AllergiesControllerTest < ActionController::TestCase
  setup do
    @allergy = allergies(:one)
    @allergy.patient = patients(:one)
  end

  test "should get index" do
    get :index
    assert_response :success
    assert_not_nil assigns(:allergies)
  end
  ...

The fixtures:

# For Allergy
one:
  name: MyString
  desc: MyText
  patient_id: 1

two:
  name: MyString
  desc: MyText
  patient_id: 1

#For Patient
one:
  first_name: Jose
  last_name: Rizal
  middle_name: H
  dob: 2009-10-29

two:
  first_name: MyString
  last_name: MyString
  middle_name: MyString
  dob: 1982-02-11

The error:

AllergiesControllerTest:
     PASS should create allergy (0.22s) 
     PASS should destroy allergy (0.01s) 
     PASS should get edit (0.13s) 
    ERROR should get index (0.14s) 
          ActionView::Template::Error: undefined method `full_name' for nil:NilClass
          /Users/wenbert/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.1.3/lib/active_support/whiny_nil.rb:48:in `method_missing'

     PASS should get new (0.02s) 
     PASS should show allergy (0.02s) 
     PASS should update allergy (0.02s) 

I have checked the logs and no Patient is saved when I run the test. I just get:

--- !ruby/object:Allergy
attributes:
  id: 298486374
  name: MyString
  desc: MyText
  created_at: 2012-01-09 14:28:21.000000000Z
  updated_at: 2012-01-09 14:28:21.000000000Z
  patient_id: 1
  Patient Load (0.2ms)  SELECT "patients".* FROM "patients" WHERE "patients"."id" = 1 LIMIT 1
--- !!null 
...

So, what gives?

Any replies will be greatly appreciated. I have been stuck at this for almost 4 hours now. :(

Could it be my fixtures? My Models?

Best Regards,

W

FYI: I am using Ruby on Rails 3.1


Solution

  • Your fixtures have the same names, name them as following

    allergy_one: 
      name: ... 
      patient: patient_one
    
    allergy_two:
      name: ...
    
    patient_one: 
      name: ..
    

    You will notice that I do not use patient_id in the fixtures. You need to reference the patient fixture you want as fixtures use random ids and do not start at 1.