Ruby on rails 带有params的Rails测试控制器私有方法

Ruby on rails 带有params的Rails测试控制器私有方法,ruby-on-rails,rspec,controller,private-methods,Ruby On Rails,Rspec,Controller,Private Methods,我在控制器中有一个私有方法 private def body_builder review_queue = ReviewQueueApplication.where(id: params[:review_queue_id]).first ... ... end 我只想测试body\u builder方法,它是一种为rest客户端api调用构建有效负载的方法。但是,它需要访问参数 describe ReviewQueueApplicationsControlle

我在控制器中有一个私有方法

private 
  def body_builder
    review_queue = ReviewQueueApplication.where(id: params[:review_queue_id]).first
    ...
    ...
  end
我只想测试
body\u builder
方法,它是一种为rest客户端api调用构建有效负载的方法。但是,它需要访问参数

describe ReviewQueueApplicationsController, type: :controller do
  describe "when calling the post_review action" do
    it "should have the correct payload setup" do
      @review_queue_application = ReviewQueueApplication.create!(application_id: 1)
      params = ActionController::Parameters.new({ review_queue_id: @review_queue_application.id })
      expect(controller.send(:body_builder)).to eq(nil)
    end
  end
end
如果我运行上述命令,它将发送
body_builder
方法,但随后它将中断,因为参数未正确设置,因为它们将在调用操作时正确设置

我总是可以为
body\u builder
方法创建一个条件参数,这样它要么接受一个参数,要么使用像
def body\u builder这样的参数(review\u queue\u id=params[:review\u queue\u id])
,然后在测试
控制器中发送(:body\u builder,params)
,但是我觉得更改代码以使测试通过是错误的,应该按原样进行测试


在将私有方法发送到控制器之前,如何将参数输入控制器?

我认为您应该能够替换

params = ActionController::Parameters.new({ review_queue_id: @review_queue_application.id })


你应该表现得很好。params只是控制器的一个属性(实际属性是
@\u params
,但有一些方法可以访问该ivar。尝试将
控制器。检查
放在视图中)。

我的建议是使用正确的参数实际调用RESTful入口点。如果在调用body_builder方法之前必须发生行为,则可以通过模拟和存根将执行引导到正确的路径。然后将期望值放在controller.body_builder方法上,而不仅仅是调用它。我意识到这比仅仅调用私有方法更重要,但我一直认为,如果在测试中直接调用私有方法,你就有点走出了该对象的测试“沙箱”。@jaydel,我完全明白你的意思,唯一的问题是在测试对入口点的实际调用时,它将触发已经测试过的
RestClient::Request
操作,我想假设该部分工作正常,但是忽略了有效负载的构建,如果我们向有效负载添加它不希望失败的内容。是的,我理解你的担心。我不熟悉该特定行为的细节,但是否可以模拟和存根该部分,以您想要测试的方式构建有效负载。我已经走出了我理解的环境,当然,你比我更清楚这一点。这是你问的一个很好的问题。我经历了很多关于这个问题的有争议的对话。不管出于什么原因,围绕这个话题似乎有一些“宗教”。我倾向于避免盲目地采取这些立场,并且在很多方面还没有解决问题,所以我将关注这个问题:)是的,我也有同样的感觉,我们总是这样分解控制器中的代码,能够根据每个方法的责任来测试每个方法是有意义的。但是拥有一个全局状态的参数使得单独测试它们变得很困难。你必须时刻注意rails背后的黑魔法。顺便说一句,你当然不应该测试私有方法;-)也许不应该直接测试它们?在我看来,如果它们很复杂,并且逻辑可能出错,就应该对它们进行测试。我有一个小小的策略,就是如果我遇到异常:我会立即通过编写测试来开始这个过程。通过这种方式,我知道我永远不会得到例外,我的大多数私有方法都承载着沉重的IP要求,并且会有相当多的中断。尽管发送这些方法看起来很肮脏,但我的想法是,如果真的很难测试私有方法,那么我正在编写的类就出了问题。我相信在这方面的普遍观点是,私有方法只能通过公共方法进行测试。因此,如果您的私有方法导致异常,我通常会通过使用私有方法的公共方法来测试。是的,这就是我所说的直接。您可以通过模拟和存根隔离来专门测试它们,并使用公共接口来驱动这些测试。我的主张(这只是我的观点)是a)它们应该被测试,b)您的测试不应该使用
。send
来测试它们。
controller.params = ActionController::Parameters.new({ review_queue_id: @review_queue_application.id })