In my project, I have this kind of code to test my controllers:
#encoding=utf-8
require 'spec_helper'
describe ProjectsController do
let!(:project) { build_stubbed(:project, user: user) }
let(:user) { build_stubbed(:user) }
before(:each) { sign_in user }
describe "GET 'index'" do
it "render index template" do
get 'index'
should render_template('index')
end
end
describe "GET 'show'" do
let!(:comment) { build_stubbed(:comment) }
before(:each) { Project.stubs(:find).returns(project) }
it "render show template" do
get 'show', id: project.id
should render_template('show')
end
it "create a new comment" do
Comment.expects(:new).returns(comment)
get 'show', id: project.id
end
end
describe "GET 'new'" do
it "render new template" do
get 'new'
should render_template('new')
end
end
describe "POST 'create'" do
before(:each) do
Project.stubs(:new).returns(project)
end
context "with valid data" do
before(:each) { project.stubs(:save).returns(true) }
it "redirect to project's path" do
post 'create'
should redirect_to(project)
end
it "save the project" do
lambda do
post 'create'
end.should change(user.projects, :size).by(1)
end
it "set a flash message" do
post 'create'
should set_the_flash[:notice].to("Votre projet a été ajouté")
end
end
context "with invalid data" do
before(:each) { project.stubs(:save).returns(false) }
it "render new template" do
post 'create'
should render_template('new')
end
end
end
describe "GET 'edit'" do
before(:each) do
Project.stubs(:find).returns(project)
end
it "render edit template" do
get 'edit', id: project.id
should render_template('edit')
end
end
describe "POST 'update'" do
before(:each) do
Project.stubs(:find).returns(project)
end
context "when valid" do
before(:each) { project.stubs(:update_attributes).returns(true) }
it "redirect to project's path" do
post 'update', id: project.id
should redirect_to(project)
end
it "update the project" do
project.expects(:update_attributes)
post 'update', id: project.id
end
it "set a flash message" do
post 'update', id: project.id
should set_the_flash[:notice].to("Votre projet a été modifié")
end
end
context "when invalid" do
before(:each) { project.stubs(:update_attributes).returns(false) }
it "render edit template" do
post 'update', id: project.id
should render_template('edit')
end
end
end
describe "DELETE 'destroy'" do
before(:each) do
Project.stubs(:find).returns(project)
project.stubs(:destroy)
end
it "redirect to project's path" do
delete 'destroy', id: project.id
should redirect_to(root_path)
end
it "delete the project" do
project.expects(:destroy)
delete 'destroy', id: project.id
end
it "set a flash message" do
delete 'destroy', id: project.id
should set_the_flash[:notice].to("Votre projet a été supprimé")
end
end
end
I do this for:
- Isolate my tests: I don't want to retest the model and I don't want to hit the database. It's faster.
- Test all actions that should be do by the controller
And I have these questions:
- Should I test the assignments or is to long for nothing?
How should I to stub my models? Is it better to place all stubs in a global
before(:each)
like this?... before(:each) do sign_in user Project.stubs(:find).returns(project) Project.stubs(:new).returns(project) project.stubs(:destroy) end ...
It's DRYer and cleaner but less efficient.
Should I really isolate my tests? I tested it without stubs and I lose 10 seconds. What do you think about that?
1 Answer 1
I found this answer helpful; I also like using the shoulda matchers to clean things up.
Yes, I think you should test your assignments. If you use the shoulda matchers, this becomes much less painful, for example:
describe "POST 'update'" do
context "when invalid" do
before(:each) do
project.stubs(:update_attributes).returns(false)
post 'update', id: project.id
end
it { should render_template('edit') }
it { should assign_to(:project).with(project) }
end
end
I usually stub where it's relevant rather than at a global level, but I don't have a good argument as to why besides that it's easier for me to understand when I'm reading it.
It's fine to test in isolation as long as you're testing your full stack somewhere like with cucumber or integration tests.
Explore related questions
See similar questions with these tags.