所有
测试中存在一些问题,如下所示:
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)的期望 - 只是记录创建和后续的变更评估失败了。
所以 - 问题:
这是指定作为此测试的一部分调用的控制器的期望的正确方法吗?
感谢您的帮助!
答案 0 :(得分: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
UPDATE:我应该在最新版本的Rails中添加它,忽略控制器过滤器的返回值。 (过滤器可以通过渲染内容来阻止动作执行。)但是,rspec的should_receive
替换方法的原则仍然是正确的,并且通常适用。