1

全部,

在测试中遇到一些问题,如下所示:

it "does something" do
  controller.should_receive(:some_method).once

  expect {
    post :create, some_params_hash, some_session_hash
  }.to change(Something, :count).by(1)
end

导轨侧的控制器 - 粗略示例:

class SomethingsController
  before_filter :some_method

  def create
    respond_with Something.create params[:something]
  end

  def some_method
    puts 'some_method'
  end
end

如果我删除 controller.should_receive 期望,这一切都很好,并且工作得很好。如果我保持期望 - 测试失败。

奇怪的是它并没有因为不满足的期望而失败——它实际上似乎满足了 should_receive(:some_method) 的期望——只是记录创建和随后的变更评估失败了。

所以 - 问题:

这是在作为此测试的一部分调用的控制器上指定期望的正确方法吗?

谢谢你的帮助!

4

1 回答 1

1

一个常见的 rspec 错误是认为您设置的方法期望should_receive只是监视应用程序以确保某些事情发生。但实际上它将自己插入到流程中并完全替换了方法。

因此,您的控制器some_method将被替换为只返回 nil 的控制器。返回 nil 的 before 过滤器将停止所有处理。你的动作永远不会被调用。

将您的期望更改为:

controller.should_receive(:some_method).once.and_return true

另请注意,您的示例正在测试两件事 - 它确保您的操作调用some_method并确保持久的Somethings的数量增加一。这很好,但如果你真的只打算检查后者,你可以使用存根而不是期望,它更紧凑一点:

controller.stub some_method: true

更新:我应该补充一点,在最新版本的 Rails 中,控制器过滤器的返回值被忽略了。(过滤器可以通过渲染一些东西来阻止动作执行。)但是,rspecshould_receive替换你的方法的原理仍然是正确的并且普遍适用。

于 2012-04-17T22:03:09.247 回答