methodofaction
methodofaction

Reputation: 72455

Application variable is nil in testing environment

My application works fine, but I can't get a test to pass. I'm new at rails so forgive me if the answer is obvious.

I need a variable available to every view, so I'm doing this within application_controller.rb:

class ApplicationController < ActionController::Base
  protect_from_forgery
  before_filter :course
  def course
    @course = Course.find_slug(params[:course])
  end
end

My test case looks like this:

it "creates an attempt" do
  sign_in current_user 
  params = {:id => challenge.id, :description => "this was hard!", :course => "design"}
  @course = FactoryGirl.create(:course)
  post :completed, params
  response.should redirect_to "/#{@course.slug}/?challenge_slug=" + challenge.slug
  Attempt.count.should == 1
  Attempt.last.description.should == params[:description]
end

The method within my controller looks like this:

  def completed
    @challenge = Challenge.find(params[:id])
    @challenge.completed(current_user, params)
    redirect_to "/#{@course.slug}/?challenge_slug=" + @challenge.slug.to_s
  end

All this works fine if I'm using the application, but the test says:

  1) ChallengesController completing a challenge creates an attempt
     Failure/Error: post :completed, params
     NoMethodError:
       undefined method `slug' for nil:NilClass
     # ./app/controllers/challenges_controller.rb:16:in `completed'
     # ./spec/controllers/challenges_controller_spec.rb:36:in `block (3 levels) in <top (required)>'

If I hardcode my controller to say redirect_to "#{'expected_value'}" then the test passes, so it seems that within the testing environment I don't have access to the application variable @course, is this correct?

I'm lost on how to solve this. Any help is appreciated.

Upvotes: 0

Views: 168

Answers (1)

Gazler
Gazler

Reputation: 84180

One solution is to stub the find method and return the instance variable.

before(:each) do
  @course = FactoryGirl.create(:course)
  Course.stub(:find_slug).and_return(@course)
end

This makes your tests more robust as the test for "find_slug" should be in your Course model, not the controller.

Upvotes: 1

Related Questions