预期:收到任何参数的时间为1次:任何参数为0次

时间:2015-08-25 16:56:07

标签: ruby-on-rails rspec mocking

我正在测试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 

请注意,我还没有完成测试,所以请省略任何评论:干掉代码等。

感谢帮助伙伴/加尔斯! :)

2 个答案:

答案 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]设置为适当的值,并将其中一个丢失,并测试响应是否在每种情况下都是预期的。您不需要检查整个响应,只需验证是否返回了正确的数据。

要使测试返回正确的响应,请为每个测试使用不同的数据集。模型将返回预期的行,并且通过测试。

现在这看起来似乎比模拟和存根更多的工作,并且运行需要更多时间,但它是测试请求的正确方法。您想要检查整个堆栈,而不仅仅是控制器中的方法调用。由此产生的测试将是真正的集成测试,并且由于它们没有与实现相结合,因此将不那么脆弱。