views:

37

answers:

1

I've recently just added Devise to my first Rails3 app, and I'm having a bit of trouble with the controller tests.

I'm testing the User controller class, which is the same model that Devise uses. So at the beginning of my spec I have this:

before(:each) do
  sign_in @user = Factory.create(:user)
end

Now I can get the test passing without using mocking or stubbing like so:

describe "GET edit" do
  it "assigns the requested user as @user" do
    user = Factory(:user)
    get :edit, :id => user.id
    assigns(:user).should eql(user)
  end
end

But for educational purposes I would like to know how to get it to work with mocking and stubbing, normally it would be completely straight forward, but it seems Devise is calling User.find before the controller action, and making the test fail.

describe "GET edit" do
  it "assigns the requested user as @user" do
    user = Factory(:user)
    User.expects(:find).with(:first, :conditions => {:id => 37}).returns(user)
    get :edit, :id => '37'
    assigns(:user).should be(user)
  end
end

Also by adding twice onto the expectation this would also fail because the first call to find is different to the one I'm setting the expectation for.

Any insight would be appreciated.

+1  A: 

You can specify multiple return values with either stubs or expects like so:

require 'test/unit'
require 'mocha'

class Foo
end

class FooTest < Test::Unit::TestCase

  # This passes!
  def test_multiple_returns_with_stubs
    Foo.stubs(:find).returns('a').returns('b').returns('c')

    assert_equal('a', Foo.find('z'))
    assert_equal('b', Foo.find('y'))
    assert_equal('c', Foo.find('x'))
  end

  # This passes too!
  def test_multiple_returns_with_expects
    Foo.expects(:find).times(1..3).returns('a').returns('b').returns('c')

    assert_equal('a', Foo.find('z'))
    assert_equal('b', Foo.find('y'))
    assert_equal('c', Foo.find('x'))
  end
end

The difference, apparently, is that expects needs to know how many times it's going to be called. If you don't specify anything, it assumes once and will complain on the subsequent calls. stubs doesn't care.

rspeicher
Thanks so much, I arrived at a similar conclusion. Is there any work around for having a different `.with` for different calls? I guess another way around would be to stub the hell out of Devise...
stuartc