遇到Rspec有问题(双倍)。收到(:消息)

时间:2014-08-26 19:15:17

标签: ruby-on-rails ruby rspec

受到Sandi Metz的编写测试方法(http://www.confreaks.com/videos/2452-railsconf2013-the-magic-tricks-of-testing)的启发,我试图重构Rails控制器的测试,断言它正在正确发送命令消息。

以下是申请的相关部分:

class DealsController < ApplicationController def index if params[:reset] deal_filter.reset ...

class ApplicationController def deal_filter ... @deal_filter ||= DealFilter.new(args) end ...

class DealFilter def reset ...do work... end ...

这是rspec测试:

describe DealsController do it "should send 'reset' to the deal_filter" do df = instance_double("DealFilter") get :index, reset: "true" expect(df).to receive(:reset) end end

不断回归的测试结果是:

1) DealsController GET index for any user params contain 'reset' should send 'reset' to the deal_filter Failure/Error: expect(df).to receive(:reset) (Double "DealFilter (instance)").reset(any args) expected: 1 time with any arguments received: 0 times with any arguments

我已经确认重置参数正在通过测试发送,并且控制器正在遵循相应的路径,但测试仍然失败。

任何人都可以提出失败的可能原因或进一步研究的资源吗?我对面向对象思想和使用Rspec的模拟相对较新。难道我误解了双打的角色吗?

谢谢你的时间!

2 个答案:

答案 0 :(得分:1)

您需要确保双重使用。我认为这里最好的方法是将deal_filter方法存根以返回double。

我补充说我会孤立这一点,因此它是it区块中唯一的东西。这样可以更轻松地添加更多的预期而无需重复设置逻辑。

describe DealsController do
  let(:df) { instance_double("DealFilter") }

  before do
    allow(controller).to receive(:deal_filter).and_return(df)
    get :index, reset: "true"
  end

  it "should send 'reset' to the deal_filter" do
    expect(df).to have_received(:reset)
  end
end

答案 1 :(得分:0)

我认为您希望在index操作中的某个位置自动使用instance_double。这不是双打工作的方式。您可以创建一个double并将其用于事物,但是控制器中的代码不会(也不应该)知道关于该double的任何内容,因此不会在其上调用任何内容。

有关如何实际使用实例double的示例,请参阅this documentation

您期望的另一个问题是您没有及早设置它。当你期望一个对象接收一个方法调用时,需要在那之后发生一些会调用该方法的东西。在您的示例中,期望接收:reset是示例的最后一行。

我建议reading up关于其他人如何使用rspec测试控制器作为一个良好的起点。