[rspec-users] (rspec2/rails3) spec'ing the details of a controller that is not purely *skinny* by design.

Frank J. Mattia frankjmattia at gmail.com
Fri Jul 9 08:29:37 EDT 2010

> > > Seems reasonable to me. You could test with either an interaction based
> > > approach (use mocks and stubs to confirm that @object receives the
> > > "created_by" message with the expected param) or a state based approach
> > > (hit the controller action and then inspect the system state afterwards
> > > to confirm that it is in the expected state).
> > What I was trying to do on my own felt a lot like what you're calling
> > an interaction based approach. I want to leave the behavior testing of
> > my app to cuke features and I'm thinking that if I'm writing a
> > controller spec, then it would probably be right to test the internals
> > of my controllers.
> I wouldn't say that "behavior" is only for Cucumber. Back when Cucumber
> hadn't even been imagined yet, RSpec was created as a "Behavior-Driven
> Development" library. Behavior has always been central to what we do
> with RSpec, even at the lowest levels.
> I think an important question to ask yourself when writing specs is
> "_Why_ am I doing this?", and that leads on to "_What_ am I interested
> in specifying here?". For me it's _all_ about behavior.

In retrospect, that's absolutely right. I think what I should have
said was I want separation of granularity in my behaviors. The model
being the most fine grained and the features being the most coarse -
with just enough overlap as to not leave any holes but not so much as
to make senseless duplication.

> The specs have two purposes, then: to document/show the behavior (when read),
> and to confirm/test the behavior (when executed). If I find myself writing
> a test that neither shows nor tests behavior, then I probably shouldn't be writing it.

That's been a good barometer for me too.

> > it "should explicitly set created_by" do
> >  controller.stub(:current_user) { mock_user }
> >  mock_order.should_receive(:created_by=).with(mock_user)
> >  post :create
> > end
> > This is my newly working spec. Does this look well thought out or is
> > there some glaring pitfall to doing it this way?
> Well, this is the way mocking and stubbing works. If you want to set an expectation on an object that doesn't exist yet at the time you're setting up the spec, you have to "chain" things so as to inject a mock of your own at the right place, which you've done here. The amount of work you have to do setting this up will vary from case to case.
> This is one of the costs of the interaction-based approached, and you have to weigh up that cost against the benefits.

Out of curiosity, how would you do this with a state based approach?
I've tried checking the value of created_by after post :create but my
assign(:order) has no idea what :created_by is.
assigns(:order).created_by.should eq(mock_current_user) just doesn't
do what I thought it would.


More information about the rspec-users mailing list