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.
One solution is to stub the find method and return the instance variable.
This makes your tests more robust as the test for “find_slug” should be in your Course model, not the controller.