[rspec-users] How To Spec Controllers with Finders

s.ross cwdinfo at gmail.com
Sat Jan 6 12:09:10 EST 2007


Wow! Thanks. I'll look at this to see how it works for me.

Steve

On Jan 6, 2007, at 5:20 AM, David Chelimsky wrote:

> On 1/6/07, s.ross <cwdinfo at gmail.com> wrote:
>> What I came up with was:
>>
>> context "The cart controller" do
>>      controller_name "carts"
>>      integrate_views
>>
>>      setup do
>>          @cart = mock("cart")
>>          @cart.stub!(:new_record).and_return(false)
>>          @cart.stub!(:new).and_return(@cart)
>>          @cart.stub!(:total_price).and_return(35.00)
>>          @cart.stub!(:total_quantity).and_return(1)
>>          @cart.stub!(:empty?).and_return(false)
>>
>>          @line_item = mock("line_item")
>>          LineItem.stub!(:find_by_id).and_return(@line_item)
>>          @line_item.should_receive(:update_attribute).with(:quantity,
>> "1").and_return(true)
>
> I try to avoid using should_receive in setup, so I'd do this here:
>
> @line_item.stub!(:update_attribute).and_return(true)
>
> and then override the method stub w/ a mock expectation in the specify
> block. The idea is that you put all of the stuff in setup that must be
> there for the code to execute, and put the details in the specs that
> are interesting for that spec.
>
>>          @line_item.stub!(:extension).and_return(25.00)
>>      end
>>
>>      specify "should allow change of quantity" do
>>          post :change_quantity, {:id => 1, :quantity => 1}
>>          response.should_be_success
>>          assigns[:extension_id].should == "extension1"
>>          assigns[:line_item].should_be(@line_item)
>>          controller.should_render_rjs :replace_html, 'cartstatus',
>> "(1 item, $35.00)"
>>      end
>> end
>>
>> but somehow it seems a bit brittle. This is really what should happen
>> if a user changes quantity, but the mocks seem like they won't flex
>> or bend easily for further reuse. Any thoughts on this?
>
> Within this context they absolutely will flex or bend by overriding
> the method stubs (functioning as defaults) w/ mock expectations.
>
> Also, I might approach this differently. The behaviour here that you
> want to spec is that when changing quantity some things should happen.
> So....
>
> context "Given a request to change quantity, the CartController  
> should" do
>   controller_name "carts"
>   integrate_views
>
>   setup do
>     @cart = mock("cart")
>     @cart.stub!(:new_record).and_return(false)
>     @cart.stub!(:total_price).and_return(35.00)
>     @cart.stub!(:total_quantity).and_return(1)
>     @cart.stub!(:empty?).and_return(false)
>     Cart.stub!(:new).and_return(@cart)
>
>     @line_item = mock("line_item")
>     @line_item.stub!(:update_attribute).and_return(true)
>     @line_item.stub!(:extension).and_return(25.00)
>     LineItem.stub!(:find_by_id).and_return(@line_item)
>
>     post :change_quantity, {:id => 1, :quantity => 1}
>   end
>
>   specify "respond w/ success" do
>     response.should_be_success
>   end
>
>   specify "assign exension_id" do
>     assigns[:extension_id].should == "extension1"
>   end
>
>   specify "assign line_item" do
>     assigns[:line_item].should_be(@line_item)
>   end
>
>   specify "update the html (using rjs)" do
>     controller.should_render_rjs :replace_html,
>       'cartstatus',
>       "(1 item, $35.00)"
>   end
> end
>
> This would then read:
>
> Given a request to change quantity, the CartController should
> - respond w/ success
> - assign exension_id
> - assign line_item
> - update the html (using rjs)
>
> If you're concerned about reuse of the stubs, you can do this:
>
> module Stubs
>   def new_stub_cart
>     cart = mock("cart")
>     cart.stub!(:new_record).and_return(false)
>     cart.stub!(:total_price).and_return(0.0)
>     cart.stub!(:total_quantity).and_return(0)
>     cart.stub!(:empty?).and_return(false)
>     cart
>   end
>
>   def new_stub_line_item
>     line_item = mock("line_item")
>     line_item.stub!(:update_attribute).and_return(true)
>     line_item.stub!(:extension).and_return(0)
>     line_item
>   end
>
>   def stub_cart
>     @stub_cart ||= new_stub_cart
>   end
>
>   def stub_line_item
>     @stub_line_item ||= new_stub_line_item
>   end
> end
>
> context "Given a request to change quantity, the CartController  
> should" do
>   include Stubs
>   controller_name "carts"
>   integrate_views
>
>   setup do
>     Cart.stub!(:new).and_return(stub_cart)
>     LineItem.stub!(:find_by_id).and_return(stub_line_item)
>   end
>   ...
> end
>
> Now any new spec that requires specific values can use
> stub_cart.should_receive(:total_price).and_return(25.00), for example.
>
>
>>
>> On Jan 5, 2007, at 2:14 PM, Courtenay wrote:
>>
>>> try this:
>>>
>>>
>>> @line_item = mock("line_item")
>>> LineItem.should_receive(:find_by_id).with(3).and_return(@line_item)
>>> @line_item.should_receive(:update_attribute).with(:quantity, 1)
>>>
>>> get :change_quantity, :id => 3, :quantity => 1
>>>
>>>
>>> On 1/5/07, s.ross <cwdinfo at gmail.com> wrote:
>>>> Given this code (which renders rjs), I'm faced with the fixture-
>>>> driven way of spec-ing or mocking. How the heck to you mock this so
>>>> the code at line (2) and (4) work right? I'm still struggling with
>>>> mocks but it seems like this can be done. Forgive the naivety of  
>>>> this
>>>> question.
>>>>
>>>> 1.  def change_quantity
>>>> 2.    @line_item = LineItem.find_by_id(params[:id])
>>>> 3.    unless @line_item.nil?
>>>> 4.      @line_item.update_attribute(:quantity, params[:quantity])
>>>> 5.      @extension_id = "extension#{params[:id]}"
>>>> 6.    end
>>>> 7.  end
>>>>
>>>> Thanks
>>>> _______________________________________________
>>>> rspec-users mailing list
>>>> rspec-users at rubyforge.org
>>>> http://rubyforge.org/mailman/listinfo/rspec-users
>>>>
>>> _______________________________________________
>>> rspec-users mailing list
>>> rspec-users at rubyforge.org
>>> http://rubyforge.org/mailman/listinfo/rspec-users
>>
>> _______________________________________________
>> rspec-users mailing list
>> rspec-users at rubyforge.org
>> http://rubyforge.org/mailman/listinfo/rspec-users
>>
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users



More information about the rspec-users mailing list