[rspec-users] Collection proxies need to be stubbed ?
David Chelimsky
dchelimsky at gmail.com
Sun Jan 21 06:37:59 EST 2007
On 1/20/07, Francois Beausoleil <francois.beausoleil at gmail.com> wrote:
> Hi all !
>
> I just started writing specs on a new project. I would just like to
> validate that this is the way you would write it. I know about mocks,
> stubs and expectations. I don't think this is a problem for me.
>
> My question really boils down to:
>
> def index
> @projects = current_user.projects.active
> end
>
> My spec needs to return the proxy, no ? Here's my code:
>
> context "A logged in user visiting the index action" do
> controller_name :dashboard
>
> setup do
> @user = mock("user")
> controller.stub!(:current_user).and_return(@user)
>
> @user.should_receive(:projects).and_return(projects_proxy = Object.new)
> projects_proxy.should_receive(:active).and_return([:a, :b])
> get :index
> end
>
> specify "should have a list of projects available" do
> assigns[:projects].should == [:a, :b]
> end
>
> specify "should render the index view" do
> controller.should_render :template => "dashboard/index"
> end
>
> specify "should be a successful call" do
> response.should_be_success
> end
> end
I would approach this quite differently. The first difference being I
would have started with a spec, letting the spec help me to discover
the interface that I want on User.
context "A logged in user visiting the index action" do
controller_name :dashboard
setup do
@user = mock("user")
controller.stub!(:current_user).and_return(@user)
@user.should_receive(:active_projects).and_return([:a, :b])
get :index
end
specify "should have a list of projects available" do
assigns[:projects].should == [:a, :b]
end
specify "should render the index view" do
response.should_render :template => "dashboard/index"
end
specify "should be a successful call" do
response.should_be_success
end
end
This would lead me to this implementation ...
def index
@projects = current_user.active_projects
end
... which would, in turn, lead me to spec out a method named
active_projects on User.
The other thing that I've been doing lately is making an effort to
separate out the noise (in setup) from the interesting bits in each
specification. I do that by using stub! in setup and should_receive in
specify, using should_receive to override stub! when appropriate. This
leads to a more verbose spec, but it makes each specify block complete
(so you don't have to look back at setup).
context "A logged in user visiting the index action" do
controller_name :dashboard
setup do
@user = mock("user")
@user.stub!(:active_projects).and_return([])
controller.stub!(:current_user).and_return(@user)
end
specify "should have a list of projects available" do
#given
@user.should_receive(:active_projects).and_return([:a, :b])
#when
get :index
#then
assigns[:projects].should == [:a, :b]
end
specify "should render the index view" do
#given - nothing unusual
#when
get :index
#then
response.should_be_success
response.should_render :template => "dashboard/index"
end
end
Here I've identified in each spec the Given/When/Then with comments.
Note that I abhor comments like this in production code, but I've come
to view specs as different from code. The result is that each spec is
easy to read and understand in isolation. You don't have to look up at
setup to understand a problem.
Note also that I've used two expectations in one spec. For me, having
a separate spec for should_be_success is not that meaningful when
we're spec'ing the template. From a developer standpoint it might be
helpful to have the statement there when trying to understand a
problem, but from the outside we know it was successful if the right
template shows up, no?
A little more than 2 cents. Hope this is all helpful.
Cheers,
David
>
> Thanks !
> --
> François Beausoleil
> http://blog.teksol.info/
> http://piston.rubyforge.org/
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
More information about the rspec-users
mailing list