views:

17

answers:

1

The idea is as follows: when visiting a purchase page, the pre-initialized (using before_filter) @purchase variable receives save if the item in question is not free.

I make two gets, one for a paid item and one for a free item. purchase.expects(:save).returns(true) expects :save to be called only once, so the below test works.

But this is really really ugly. The test it incredibly lengthy. What would be a better way to do this? Should I mock the find_or_initialize method? If so, how would I set the @purchase instance variable?

Sorry for the ugly code below...

  def test_new_should_save_purchase_if_not_free       
    user = users(:some)
    purchase = user.purchases.build 
    @controller.stubs(:current_user).returns(user)
    purchases_mock = mock
    user.stubs(:purchases).returns(purchases_mock)
    purchases_mock.stubs(:build).returns(purchase)
    purchase.expects(:save).returns(true)
    get :new, :item_id => items(:not_free).id, :quantity => 10
    get :new, :item_id => items(:free).id, :quantity => 400
  end

  def new                                                         
    @purchase.quantity = params[:quantity]
    @purchase.item = Item.find(params[:item_id])
    unless @purchase.item.free?
      @purchase.save
    end
  end

  def find_or_initialize
    @purchase = params[:id] ? current_user.purchases.find(params[:id]) : current_user.purchases.build
  end   
A: 

It looks like you're already using fixtures for your items, why not just use a fixture for the Purchase as well? There is no need to go through all that effort to stub the user.

Karl
Hi Karl, the test suite existed when I took on the project so I decided I might as well use existing fixtures, though I usually avoid fixtures in my own projects. So, without fixtures and only mocks, how would I avoid that whole mess?
Alexandre