【问题标题】:Testing two different expectations with mocking用 mocking 测试两种不同的期望
【发布时间】:2010-07-28 13:27:06
【问题描述】:

我最近刚刚将 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 与我设置期望的不同。

任何见解将不胜感激。

【问题讨论】:

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


    【解决方案1】:

    您可以使用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 不在乎。

    【讨论】:

    • 非常感谢,我得出了类似的结论。对于不同的呼叫有不同的.with 有什么解决方法吗?我想另一种方法是从 Devise 中剔除地狱......
    猜你喜欢
    • 2021-08-04
    • 2021-11-22
    • 2022-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-18
    相关资源
    最近更新 更多