On Aug 30, 2010, at 12:54 PM, Brennon Bortz wrote:
On 30 Aug 2010, at 17:17, Justin Ko wrote:
On Aug 30, 11:59 am, Brennon Bortz <bren...@brennonbortz.com> wrote:
I am, as usual, assigning an instance variable in a controller's index action to find all instances of a model in the database. I want to write a spec that checks that this variable is assigned correctly. I can do:

it "should provide a collection of widgets in @widgets" do
     widget = Widget.create("title" => "my widget")
     get :index
     assigns[:widgets].should include(widget)
end

or:

it "should provide a collection of widgets in @widgets" do
     widget = Factory.create(:widget)
     get :index
     assigns[:widgets].should include(widget)
end

Is there a better way to do this with a mock model, though?

Thanks,

Brennon Bortz
Software Researcher
Dundalk Institute of Technology
brennon.bo...@casala.ie
Ph.D. Researcher & Composer - Sonic Arts Research Centre
Queen's University, Belfast
bren...@brennonbortz.com / bbort...@qub.ac.uk

_______________________________________________
rspec-users mailing list
rspec-us...@rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users

Currently, what you're doing is checking that the Widget model returns
the correct widgets. If you want to isolate your controller spec from
the model, you must stub or mock the model method call in the action.
Example:

it "..." do
widget = mock_model(Widget)
Widget.should_receive(:all).and_return([widget])
get :index
assigns[:widgets].should include(widget)
end

To check that Widget.all does indeed return the correct widgets, I
would spec that behaviour in the Widget model spec.

Hope that helps.

Hrm...that's exactly what I'd started with, and I was getting the following error:

Failures:
1) WidgetsController GET 'index' should provide a collection of widgets in @widgets
    Failure/Error: assigns[:widgets].should include(widget)
    expected [] to include #<Widget:0x81686290 @name="Widget_1001">

Stupidly, I had defined my controller method as:

def index
 @widgets = Widget.find(:all)
end

Changed that assignment to Widget.all...problem solved.

And THAT is the problem with using mocks (or stubs) for this. You run the very real risk of specifying the implementation details in the structure of the spec/test. There is a problem when you've limited the refactoring that can be done without altering the spec/test. Since Widget.find(:all) and Widget.all should always have the same result, the mere presence of the mock has cut off one possible refactoring. (The one that I distaste most limits changing .find(params[:id]) to .find_by_id(params[:id]) by mocking/stubbing the call to find.)

Think about what really needs to be specified and be careful to mock/ stub as little as possible and to do so in a way that will limit opportunities to refactor the least.

-Rob

Rob Biedenharn          
r...@agileconsultingllc.com     http://AgileConsultingLLC.com/
r...@gaslightsoftware.com               http://GaslightSoftware.com/

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

Reply via email to