[rspec-users] Nosy controller specs

Pat Maddox pergesu at gmail.com
Thu Dec 11 13:23:10 EST 2008


"Mark Wilden" <mark at mwilden.com> writes:

> On Thu, Dec 11, 2008 at 4:33 AM, Andrew Premdas <apremdas at gmail.com> wrote:
>
>             it "should find all posts" do
>               Post.should_receive(:find).with(:all).and_return([@post])
>               do_get
>             end
>          
>         Now this last spec "should find all posts" is nosy is far as I'm concerned in that its specifying how the model should get all the
>         posts (i.e. white box testing) rather than checking the result i.e. that its got @post back. So now if I change the model so that
>         "all posts" is for example "all posts in last year" because there is a new business rule that we don't show posts over a year old
>         then my controller spec fails.
>
> I think this is probably correct as is.
>
> When specing a controller, it's correct BDD to specify how it interacts with other objects. If the controller itself wants all posts in the
> last year, it's OK to test that. The fact that only this year's posts are of interest is a presentation issue - it's not an essential
> characteristic of the data. It's not the model's job to decide that all clients should get back posts in the last year, and hence that's
> what its find method should return.
>
> All business rules don't reside in the model. As soon as you say "we don't SHOW posts over a year," you're talking about a presentation
> rule, not a model rule. Controllers mediate between data and screen - they're responsible for getting the data to be shown. That code should
> exist in the controller and be tested there.
>
> On the other hand, the controller should not necessarily be responsible for defining what constitutes "all posts in the last year." That
> should very likely be a named scope.
>
> This is all just my humble opinion, of course, and might be utter rubbish in any particular real world situation.
>
> ///ark
>
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users

I agree with this.  You generally don't want to screw with the meaning
of AR::Base.find.  That's really only for situations where you want some
uniform, transparent behavior (acts_as_versioned, acts_as_paranoid,
etc).

The view shouldn't really care about this stuff either...it should just
take a list of posts and display them.

It's up to the controller to ask the model for what it wants to push to
the view.  So your finder can be something like Post.since(1.year.ago)
or whatever.

Andrew, I've noticed a theme in your posts that suggests you feel you
needn't ever change controller specs.  That's just not true.  Models
are a distilled representation of the domain, and controllers give
meaning to it in the context of the application you're working on.
Models are what your app *is* and controllers are what your app *does*.
When you change what your app does, you're going to have to change some
specs and production code along with it.

Keep in mind that if you went with a state-based test, you would *still*
have to modify the controller spec.  It wouldn't be good enough to
expect a post to be displayed.  You'd have to create a post with a
created_at of over a year ago, and one within the last year, and expect
that the former is not shown while the latter is.

Also, I'd like to point out that if you *really* wanted Post.find(:all)
to only return posts in the last year, you wouldn't actually have to
change the controller spec :)  You would just have to write a model spec
for that behavior.

Pat


More information about the rspec-users mailing list