用嘲弄测试两种不同的期望

时间:2010-07-28 13:27:07

标签: ruby-on-rails ruby rspec mocha rspec2

我最近刚刚将Devise添加到我的第一个Rails3应用程序中,我在控制器测试方面遇到了一些麻烦。

我正在测试User控制器类,它与Devise使用的模型相同。所以在我的规范开头我有这个:

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

现在,我可以在不使用模拟或存根的情况下通过测试:

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

但是出于教育目的,我想知道如何让它与模拟和存根一起工作,通常它会完全直截了当,但似乎Devise在控制器操作之前调用User.find,并且测试失败。

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

同样通过将twice添加到期望中,这也会失败,因为第一次调用find与我正在设置的期望不同。

任何见解都将受到赞赏。

1 个答案:

答案 0 :(得分:5)

您可以使用stubsexpects指定多个返回值,如下所示:

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

显然,差异在于expects需要知道要调用多少次。如果您未指定任何内容,则会假定为once,并会在后续调用中抱怨。 stubs不关心。