1
\$\begingroup\$

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?

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Jun 28, 2012 at 16:35
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

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.

answered May 14, 2013 at 23:17
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.