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

Wincent Colaiuta win at wincent.com
Fri Jul 9 01:56:12 EDT 2010

El 09/07/2010, a las 04:25, Frank J. Mattia escribió:

>> 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. 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.

So, with the focus always on the behavior of the action, you can proceed to do either interaction-based or state-based testing, depending on what feels right for each particular case. As I mentioned in my earlier email, there are costs and benefits of each approach, and long running debates about which method to use when, but I think the important thing is to always try to use the best tool for the job at hand.

> (As an aside, I've only been using RSpec for ~3
> weeks now and testing in general for maybe a month. All of this is
> pretty new to me... I find myself quickly becoming 'opinionated' about
> things so if any of this sounds like nonsense, a pointer in a good
> direction would be happily accepted.)

I think the best way to learn is to do what you're already doing: writing specs (lots of them), _thinking_ about what you're doing, and when you have doubts asking questions or looking for better ways. As time goes by you'll not only get better at it, but your thinking will probably evolve too. I know I've gone back and forth many times over the years, and sometimes I get a surprise when I stumble over an old blog post of mine on testing and see what I posted.

I think if you look at what the most influential people in the Ruby/RSpec testing community have been saying over the years, you'll see how _their_ ideas have been metamorphosing and changing over the years too. It's a natural part of thoughtful testing, I think.

El 09/07/2010, a las 06:07, Frank J. Mattia escribió:

> 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.


More information about the rspec-users mailing list