首页 > 解决方案 > 如何使用 minitest 在控制器上测试私有方法?

问题描述

非常新的测试

我有一个无模型的 Rails 应用程序,带有一个名为“PokerController”的控制器

在 poker_controller.rb 中,我有一个如下所示的私有方法:

  private

  def test(x)
    1 + x
  end

然后我在测试/控制器中有一个名为“poker_controller_test.rb”的文件

我正在尝试做这样的事情:

require 'test_helper'

class PokerControllerTest < ActionController::TestCase

  test "check if test == 2" do
    test = test(1)
    assert test == 2
  end

end

如您所见,我正在尝试将调用函数“test”的结果保存到名为“test”的变量中,然后我正在检查是否 == 2。

基本上,我试图将一个数字(在本例中为“1”)传递给测试方法,并且我希望测试将 1 加到 1,并期望得到 2。

我确定我只是没有正确设置测试,但是如何调用这样的自定义方法然后评估返回的内容?

这是我的测试错误结果:

Error:
PokerControllerTest#test_check_if_test_==_2:
ArgumentError: unknown command "\x01"
    test/controllers/poker_controller_test.rb:6:in `test'
    test/controllers/poker_controller_test.rb:6:in `block in <class:PokerControllerTest>'

标签: ruby-on-railsrubyminitest

解决方案


你没有。

通常不赞成测试私有方法*。

在 Rails 中,您主要通过集成测试来测试控制器。这些测试向您的应用程序发送真正的 HTTP 请求,然后您编写有关响应或发送请求的副作用的断言。

“[...] 您可以测试设置了哪些 cookie、返回了哪些 HTTP 代码、视图的外观或数据库发生了哪些变化,但测试控制器的内部结构并不是一个好主意。”
——大卫·海涅迈尔·汉森

集成测试的一个例子是:

require "test_helper"

class PokerControllerTest < ActionDispatch::IntegrationTest
  test "can see the welcome page" do
    get "/path/to/somewhere"
    assert_select "h1", "Welcome to my awesome poker app"
  end
end

如果您有一个要单独测试的方法,它首先不属于您的控制器,并且可以说它也不应该是私有方法。

您应该测试对象的公共 API。控制器的公共 API 是通过路由器响应 HTTP 请求的方法。

ActionController::TestCase鼓励在遗留应用程序之外使用。

新的 Rails 应用程序不再生成函数式控制器测试,它们只能用于向后兼容。集成式控制器测试执行实际请求,而功能式控制器测试仅模拟请求。此外,集成测试与功能测试一样快,并提供了许多帮助程序,例如 parsed_body 用于有效测试控制器操作,甚至包括 API 端点。

除此之外,您的测试问题是您正在调用test实例ActionController::TestCase而不是控制器上的方法。然后,您通过定义具有相同名称的实例变量来隐藏该方法,这很少是一件好事。

即使您确实调用了控制器上的方法,Ruby 仍然会引发错误,因为您是从对象外部调用私有方法 - 这就是私有方法的全部意义所在。

虽然你可以通过调用它来违反封装,@controller.send(:test)但这在很多层面上都是一个坏主意。


推荐阅读