我正在测试index
的{{1}}操作。
我正在使用will_paginate gem,并且我正在尝试编写一个RSpec测试,以确保在project_path时对当前用户的项目调用paginate方法。
然而,我得到的结果并不是我的预期,我无法弄清楚为什么。
结果
ProjectsController
项目#索引
Failure/Error: expect(user.projects).to receive(:paginate)
(#<ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Project:0x00000004719ef0>).paginate(any args)
expected: 1 time with any arguments
received: 0 times with any arguments
# ./spec/requests/project_pages_spec.rb:82:in `block (3 levels) in <top (required)>'
指数测试
def index
if params[:search]
@projects = current_user.projects.search(params[:search]).paginate(:page => params[:page], :per_page => 13)
else
@projects = current_user.projects.paginate(:page => params[:page], :per_page => 13)
end
end
请注意,我还没有完成测试,所以请省略任何评论:干掉代码等。
感谢帮助伙伴/加尔斯! :)
答案 0 :(得分:4)
失败的原因是您的spec文件中的user
与控制器中的current_user
不同。因此,虽然current_user
正在接收paginate
,但您的规范user
永远不会。有几种方法可以解决它。
你可以这样做:
expect_any_instance_of(User).to receive(:paginate)
这里的缺点是您正在测试任何实例,而不是您的current_user
实例。这是否是一个问题取决于你:)
另一种方式是存根current_user
:
controller.stub(:current_user).and_return(user)
expect(user.projects).to receive(:paginate)
好处是你正在测试完全相同的用户。缺点是current_user
可能会引入其他问题。
答案 1 :(得分:0)
您感受到的部分痛苦在于您正在测试实现而不是行为。通常,Web请求的行为可以用几个词来描述:它接受输入参数并返回响应。要测试行为,请测试响应的内容。
在您的情况下,应用程序在params[:search]
出现时会以一种方式运行,而在缺少时则采用另一种方式。因此,编写一个测试,params[:search]
设置为适当的值,并将其中一个丢失,并测试响应是否在每种情况下都是预期的。您不需要检查整个响应,只需验证是否返回了正确的数据。
要使测试返回正确的响应,请为每个测试使用不同的数据集。模型将返回预期的行,并且通过测试。
现在这看起来似乎比模拟和存根更多的工作,并且运行需要更多时间,但它是测试请求的正确方法。您想要检查整个堆栈,而不仅仅是控制器中的方法调用。由此产生的测试将是真正的集成测试,并且由于它们没有与实现相结合,因此将不那么脆弱。