Ruby on rails Rspec expect(double)有问题。无法接收(:消息)

Ruby on rails Rspec expect(double)有问题。无法接收(:消息),ruby-on-rails,ruby,rspec,Ruby On Rails,Ruby,Rspec,受到Sandi Metz编写测试()方法的启发,我正在尝试重构Rails控制器的测试,以断言它正确地发送了命令消息 以下是应用程序的相关部分: class DealsController

受到Sandi Metz编写测试()方法的启发,我正在尝试重构Rails控制器的测试,以断言它正确地发送了命令消息

以下是应用程序的相关部分:

class DealsController

类应用程序控制器
def deal_过滤器
...
@deal|u filter | |=DealFilter.new(args)
结束
...

类过滤器
def复位
……工作。。。
结束
…

以下是rspec测试:

description DealsController do
它“应将‘重置’发送到交易过滤器”do
df=实例双(“DealFilter”)
获取:索引,重置:“真”
预期(df).接收(:重置)
结束
结束

不断返回的测试结果包括:

1)包含“reset”的任何用户参数的DealsController获取索引应将“reset”发送到deal\u筛选器
失败/错误:预期(df).接收(:重置)
(双重“DealFilter(实例)”).reset(任何参数)
预期:1次,有任何参数
收到:0次,有任何参数

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

有人能提出失败的可能原因或进一步研究的资源吗?我对面向对象的思想和将mock与Rspec结合使用还比较陌生。是不是我误解了双打的角色


谢谢你的时间

我认为您希望您的instance\u double在索引操作中的某个位置自动使用。双打不是这样的。您可以创建一个double并将其用于其他用途,但是控制器中的代码不(也不应该)知道关于该double的任何信息,因此永远不会调用它

有关如何实际使用实例double的示例,请参见

另一个与你的期望有关的问题是你没有足够早地设定它。当您期望一个对象接收一个方法调用时,需要在调用该方法之后发生一些事情。在您的示例中,期望接收:重置是示例的最后一行


我建议其他人如何使用rspec测试控制器,这是一个很好的起点。

你需要确保你的双卡被使用。我认为最好的方法是存根
deal\u 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

您的代码示例非常有用。stubing语法allow()引导我走上了正确的道路。然而,@Coenwulf的预期顺序是正确的。设置期望值后,我必须放置
get:index
。在我的示例中,我应该使用
have\u receive
。现在更新了。