[rspec-users] Correct spec for a scoped controller

David Chelimsky dchelimsky at gmail.com
Tue Sep 7 07:58:01 EDT 2010


On Sep 7, 2010, at 6:01 AM, Cameron Caine wrote:

> In almost all my controllers I scope everything through an @account
> model object, e.g:
> 
> #teams_controller.rb
> def new
>  @team = @account.teams.build
> end
> 
> So far I have got passing specs using these:
> 
> describe TeamsController do
>  let(:account) { Account.new }
> 
>  before(:each) do
>    Account.stub!(:find_by_subdomain!).and_return(account)
>    account.stub!(:teams)
>  end
> 
>  describe "GET new" do
>    let(:team) { Team.new("account_id" => account.id) }
> 
>    before(:each) do
>      account.teams.should_receive(:build).and_return(team)
>    end
> 
>    it "assigns @team to a new scoped instance of Team" do
>      get :new
>      assigns[:team].should eq(team)
>    end
> 
>    it "renders the new template" do
>      get :new
>      response.should render_template("new")
>    end
>  end
> end
> 
> I am interested to know if this is best practice for scoping everything
> through an existing model object.

That's a lot of noise for two simple examples. I'd either just use AR (no stubs) or add a build_team method to Account. I also prefer to keep message expectations (should_receive) in the examples that specify the expectation. In the spec above "renders the new template" would fail for the wrong reason if the other example failed. I also like to keep the let() statements near each other since they're eval'd lazily (makes it easier to find them).

That would lead me to something like:

describe TeamsController do
  let(:account) { stub_model(Account).as_null_object }
  let(:team) { stub_model(Team) }

  before(:each) do
    Account.stub(:find_by_subdomain!) { account }
  end

  describe "GET new" do
    it "assigns @team to a new scoped instance of Team" do
      account.should_receive(:build_team) { team }
      get :new
      assigns(:team).should eq(team)
    end

    it "renders the new template" do
      get :new
      response.should render_template("new")
    end
  end
end

HTH,
David


More information about the rspec-users mailing list