【问题标题】:Rails testing controller private method with paramsRails 使用参数测试控制器私有方法
【发布时间】:2016-05-05 13:21:34
【问题描述】:

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

private 
  def body_builder
    review_queue = ReviewQueueApplication.where(id: params[:review_queue_id]).first
    ...
    ...
  end

我只想测试body_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_builder 方法创建一个条件参数,这样它要么接受一个参数,要么使用像def body_builder(review_queue_id = params[:review_queue_id]) 这样的参数,然后在测试controller.send(:body_builder, params),但我觉得更改代码使测试通过是错误的,它应该按原样进行测试。

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

【问题讨论】:

  • 我的建议是使用正确的参数实际调用 RESTful 入口点。如果在调用 body_builder 方法之前必须发生某些行为,则可以模拟和存根以将执行引导到正确的路径。然后,您对 controller.body_builder 方法寄予期望,而不仅仅是调用它。我意识到这比仅仅调用私有方法要重,但我一直觉得,如果直接在测试中调用私有私有方法,那么你有点跨出了该对象的测试“沙箱”。
  • @jaydel,我完全明白你来自哪里,唯一的问题是测试对入口点的实际调用是它会触发已经测试过的RestClient::Request 操作,我希望假设该部分正常工作,但忽略了有效负载的构建,如果我们向有效负载添加它不希望它会失败的东西。
  • 是的,我理解您的担忧。我不熟悉该特定行为的细节,但是否可以模拟和存根该部分以您想要测试的方式构建有效负载。我已经在我理解的范围之外徘徊,当然,你比我更了解它。所以只是深思
  • 这是您提出的一个很好的问题。我经历了很多关于这个问题的有争议的对话。无论出于何种原因,这个话题似乎都有一些“宗教”。我倾向于避免盲目地采取这些立场,并且在很多方面仍未解决,所以我会关注这个问题:)
  • 是的,我也有同样的感觉,我们一直都这样分解控制器中的代码,并且能够根据其职责测试每个方法是有意义的。但是拥有一个像参数这样的全局状态使得很难单独测试它们。你必须时刻注意后台的黑魔法。

标签: ruby-on-rails rspec controller private-methods


【解决方案1】:

我认为你应该可以替换

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

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

你应该很好。 params 只是控制器的一个属性(实际属性是@_params,但有一些方法可以访问该ivar。尝试将controller.inspect 放在视图中)。

【讨论】:

  • 顺便说一句,话虽如此,您当然不应该测试私有方法;-)
  • 不应该直接测试它们,也许吧?如果它们很复杂并且逻辑可能出错,我认为应该对其进行测试。
  • 我有一个小策略,如果我遇到异常:我会立即通过编写测试来启动该过程。这样我知道我永远不会遇到异常,我的大多数私有方法都承载着大量的 IP 要求并且中断了很多。尽管发送这些方法看起来很脏,但我的想法是,如果真的很难测试私有方法,那么我正在编写的类有问题。
  • 我相信对此的普遍看法是私有方法只能通过公共方法进行测试。因此,如果您的私有方法导致异常,我通常会通过使用私有方法的公共方法进行测试。
  • 是的,这就是我的意思。您可以通过模拟和存根隔离来专门测试它们,并使用公共接口来驱动这些测试。我的断言(这只是我的观点)是 a)它们应该被测试 b)你的测试不应该使用 .send 来测试它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多