> >>> 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.
>
> Ok, some qualifications:
>
> - I use factories heavily (in this example Factory Girl) to make it easier to 
> write tests. I don't worry about the slowness of using real model instances 
> until the spec suite actually becomes large enough for it to be a problem. I 
> also don't worry about the risk of cascading failures (broken model breaks 
> controller spec) because I value the simplicity that comes with keeping 
> mocking and stubbing to a minimum in the specs, and I am wary of the 
> insulation that mocking and stubbing bring and can actually hide real 
> failures (eg. API changes but spec keeps passing anyway). I still do mock and 
> stub, but generally only where it is not easier to just verify state (and it 
> often is easier).
>
> - I use RR for mocking because I like the syntax. Even in a state-based 
> approach, you'll see I have to stub out the "current_user" method on the 
> controller.
>
> - I use a "before" block that sets up @user, @params, and does the stubbing, 
> so that I can reuse the same stuff in many different "it" blocks.
>
> - And I try to keep each "it" block as short as possible, just do the post 
> then inspect the state afterwards. In this case the state that I am checking 
> for is the externally visible stuff like what got assigned (assigns), what 
> got rendered (render_template) or redirected (redirect_to), what flash or 
> cookies got set, and so on. If need be, I can query the database.
>
> - And finally, note that this is written for Rails 3/RSpec 2, which I've been 
> using solidly for the last month and have now forgotten what Rails 2/RSpec 1 
> specs looked like!
>
> So with all that said, this is more or less what my state-based approach 
> would look like:
>
>   before do
>     @user = User.make!
>     stub(controller).current_user { @user }
>     @params = { :post => { :title => 'foo', :body => 'bar' } }
>   end
>
>   it 'should set created_by' do
>     post :create, @params
>     assigns[:post].created_by.should == @user
>   end
>
>   ...
>
> The controller/action is treated as a "black box" which I never look inside. 
> Each "it" block basically just follows this pattern:
>
>   1. Feed params into the black box
>   2. Check _one_ piece of state afterwards
>
> By trying to keep only one "should" assertion in each "it" block I get nice 
> granularity in the event of failure.
>
> It is not "better" nor "the right" way, it is just "a" way of doing it. I've 
> also written controller specs where I ended up mocking left, right and 
> center, but if I can take the state-based approach I generally prefer it. The 
> app I'm currently working on has about 3,000 examples, and the suite runs 
> fast enough that I don't yet feel the need to change my emphasis away from 
> state-based testing.

Thanks for all your help. I've been toying around with a few different
approaches to these two ways and I'm starting to make sense of it all.
I too have been using Factory Girl (after spending a day creating my
own factory implementation and not knowing what it was). I can't say
I'm sold on rr but it does look promising. After trying mocha for all
of 32 seconds I just couldn't take it (any_instance made me twitch)
and went back to rspec mocking & stubbing... I'll keep it in the back
of my mind for a day that I'm feeling experimental.

Anyway, thanks again. You've been a huge help.

Cheers,
- FJM
_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users

Reply via email to