通过模拟测试两种不同的期望

发布于 2024-09-11 18:12:15 字数 896 浏览 5 评论 0原文

我最近刚刚将 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

此外,通过在期望中添加两次也会失败,因为第一次调用 find 与我设置期望的调用不同。

任何见解将不胜感激。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蘑菇王子 2024-09-18 18:12:15

您可以使用 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,并且会在后续调用中抱怨。 存根不在乎。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文