使用TDD后,使用skip_before_action的测试单元不会取消设置

时间:2018-06-07 10:11:57

标签: ruby-on-rails ruby unit-testing tdd ruby-on-rails-5.2

我正在使用Rails 5.2并进行一些测试。我正在尝试使用when(mockPersonRepository.getOne(personId)).thenReturn(person);进行单元测试,发现ActionController::TestCase在进入下一个测试单元方法之前没有自动重置控制器。

现在因为rails测试在每次运行时都是随机的,所以某些单元有时会失败而不是其他时间。我认为它期待HTTP 401,但我得到了200.因为控制器忽略了@controller.class.skip_before_action :verify_user

我可以在每个单元的末尾设置before_action :verify_user(并且它可以工作!)但是,如果不是每次运行之前重置上下文的测试系统的代表吗?

给我一​​段代码:

@controller.class.before_action :verify_user

1 个答案:

答案 0 :(得分: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的{​​{1}}和setup方法来提供此功能非常方便。 (相当于teardown中的beforeafter个钩子。