【问题标题】:Rspec expect(instance) to receive method not working as expectedRspec期望(实例)接收方法未按预期工作
【发布时间】:2017-09-27 10:56:48
【问题描述】:
#controller file
def update
  @payment = Payment.find_by(reference_id: params[:reference_id])
  if @payment.update(update_params)
    @payment.do_something
  end
end

当尝试指定是否调用了 do_something 方法时,由

expect(@payment).to receive(:do_something)

它说

expected: 1 time with any arguments
received: 0 times with any arguments

do_something 在我的支付类中。它实际上被调用了,但 rspec 说没有。

有什么想法吗?提前致谢

【问题讨论】:

    标签: ruby-on-rails ruby rspec controller rspec-expectations


    【解决方案1】:

    您在 specs 中的 @payment 实际上是一个完全不同的变量,它是 specs 类的一部分,而不是控制器。我可能错了,但这是我对您发布的代码部分的假设 - 添加规范代码以获取更多信息。 作为解决方案,可以使用“存根任何实例”

    Payment.any_instance.stub(:do_something).and_return(:smthing)

    更复杂的方法 - 使用双打

    【讨论】:

    • 这是否等同于allow_any_instance_of(Payment).to receive(:do_something).and_return(:smthing)
    • 现在我看到 any_instance 已被弃用(请参阅 relishapp.com/rspec/rspec-mocks/v/3-3/docs/old-syntax/…):any_instance 是存根或模拟类的任何实例的旧方法,但在所有类上都带有全局猴子补丁的包袱.请注意,我们通常不建议使用此功能。
    【解决方案2】:

    首先你需要在控制器中存根代码以便expect一些代码

    before do
      allow(Payment).to receive(:find_by).and_return(payment)
      allow(payment).to receive(:update).and_return(true)
      allow(payment).to receive(:do_something)
    end
    

    另外,控制器中的实例变量不能在 rspecs 中直接访问。

    所以,首先使用let 在rspecs 中创建一个支付对象,然后像我在上面的解决方案中那样使用before

    【讨论】:

    • 它有效,但在我看来,伪造 ActiveRecord 会使测试容易出现许多误报
    猜你喜欢
    • 1970-01-01
    • 2016-05-23
    • 1970-01-01
    • 2015-09-26
    • 1970-01-01
    • 2019-04-22
    • 2015-01-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多