Search code examples
ruby-on-railstestingscopemockingstub

Best approach to test scope chains in Rails


In all my ruby on rails app, I try to not use the database in controllers, since they should be independent from persistence classes. I used mocking instead.

Here is the example for rspec and rspec-mock:

class CouponsController < ApplicationController
  def index
    @coupons = Coupon.all
  end
end

require 'spec_helper'
describe CouponsController do
  let(:all_coupons) { mock } 
  it 'should return all coupons' do
    Coupon.should_receive(:all).and_return(all_coupons)
    get :index
    assigns(:coupons).should == all_coupons
    response.should be_success
  end
end

But what if controller contains more complex scopes, like:

class CouponsController < ApplicationController
  def index
    @coupons = Coupon.unredeemed.by_shop(shop).by_country(country)
  end
end

Do you know any good approach for testing simillar scopes chains?

I think that the following test does not look really good:

require 'spec_helper'
describe CouponsController do
  it 'should return all coupons' do
    Coupon.should_receive(:unredeemed).and_return(result = mock)
    result.should_receive(:by_shop).with(shop).and_return(result)
    result.should_receive(:by_country).with(country).and_return(result)
    get :index
    assigns(:coupons).should == result
    response.should be_success
  end
end

Solution

  • You could use stub_chain method for that.

    Something like:

    Coupon.stub_chain(:unredeemed, :by_shop, :by_country).and_return(result)
    

    Just an example.