1

我正在使用 Rails 5.2 并进行一些测试。我正在尝试我的单元测试,ActionController::TestCase发现@controller.class.skip_before_action :verify_user在进入下一个测试单元方法之前不会自动重置控制器。

现在因为 Rails 测试在每次运行时都是随机的,某些单元有时会失败,有时不会失败。我认为它期待 HTTP 401,但我得到了 200。导致控制器忽略before_action :verify_user.

我可以@controller.class.before_action :verify_user在每个单元的末尾设置(它可以工作!)但它不应该是测试 sys 的代表在每次运行之前重置上下文吗?

给出我的代码片段:

class ApiSiteMetricsTest < ActionController::TestCase
  tests Api::SiteMetricsController

  def test_1_index
    @controller.class.skip_before_action :verify_user,raise: false

    get "index",  params:{ 
        "format"=>"json",
        "site_metric_value"=>{
            "site_metric_id"=>2403, 
            "date_acquired"=>"2018-03-14T01:44:00+05:30", 
            "site_id"=>3840, 
            "lab_device_details"=>"", 
            "comment"=>"", 
            "sender_affiliation"=>"", 
            "float_value"=>""
        }
    }
    assert_response :success
    File.open("#{Rails.root}/del.html", "wb") { |f| f.write(@response.body) }        
    #Do I have to do this o every test?
    #@controller.class.before_action :verify_user
  end
  ...
4

1 回答 1

1

您绝对正确,每个测试都应在运行后重置系统状态。测试应该是完全独立的——这正是它们以随机顺序运行的原因(默认情况下)。

对于大多数事情——比如数据库事务——测试框架可以为你处理。但是还有无数其他方法可以改变环境。测试框架不能总是覆盖你的背部。

例如,如果你的测试改变了一个ENV变量怎么办?还是打电话Timecop.freeze?或者通过第二个数据库连接添加数据库记录?或者设置一个全局变量?...

有时,您需要手动重置状态!

在这种情况下,我会这样做:

class ApiSiteMetricsTest < ActionController::TestCase
  tests Api::SiteMetricsController

  def test_1_index
    @controller.class.skip_before_action :verify_user,raise: false

    # ...

    ensure

    @controller.class.before_action :verify_user
  end
end

ensure那里,即使这个测试失败,状态也应该被重置——因此不会影响其他测试是否失败。

在某些情况下,您可能会发现使用MiniTest'ssetupteardown方法来提供此功能很方便。(相当于 中的beforeandafter钩子rspec)。

于 2018-06-07T12:27:48.683 回答