【问题标题】:DatabaseCleaner don't reset autoincrement index in rails test unitDatabaseCleaner 不会在 Rails 测试单元中重置自动增量索引
【发布时间】:2016-07-13 09:21:27
【问题描述】:

test/test_helper.rb:

ENV["RAILS_ENV"] ||= "test"
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'database_cleaner'

DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation, pre_count: true, reset_ids: true)

class ActiveSupport::TestCase
  ActiveRecord::Migration.check_pending!


  def setup
    DatabaseCleaner.start
  end


  def teardown
    DatabaseCleaner.clean
    p '-------- DB Cleaned ---------'
  end

end

我的测试单元文件:(test1 和 2 是重复的)

require 'test_helper'

class ItemTest < ActiveSupport::TestCase

  test "test1" do
    i = Item.create!

    p ActiveRecord::Base.connection.execute("SELECT auto_increment FROM information_schema.tables WHERE table_schema = 'tmi_game_test' AND table_name = 'items';").first

    assert_equal 1, Item.count
    assert_equal 1, i.id
  end

  test "test2" do
    i = Item.create!

    p ActiveRecord::Base.connection.execute("SELECT auto_increment FROM information_schema.tables WHERE table_schema = 'tmi_game_test' AND table_name = 'items';").first

    assert_equal 1, Item.count
    assert_equal 1, i.id
  end

end

结果:

# Running:

[2]
"-------- DB Cleaned ---------"
.[3]
"-------- DB Cleaned ---------"
F

Finished in 0.142886s, 13.9972 runs/s, 27.9944 assertions/s.

  1) Failure:
ItemTest#test_test2 [test/models/item_test.rb:45]:
Expected: 1
  Actual: 2

2 runs, 4 assertions, 1 failures, 0 errors, 0 skips

为什么不工作?我的错在哪里?

【问题讨论】:

    标签: ruby-on-rails unit-testing database-cleaner


    【解决方案1】:

    这是预期的行为。您正在使用:transaction 策略来清理表。这意味着每个测试都包含在一个事务中,该事务在测试之后是ROLLBACK-ed(在teardown 期间)。

    您尚未说明您使用哪个数据库,但 ROLLBACK 不会重置 AUTO_INCREMENT,无论是在 MySQL(参见 bug #6714)还是在 PostgreSQL(参见 bug #1139)中。

    根据SO answer,我认为您永远不应该在测试中依赖 auto_increment ID 值。我认为您应该测试其他属性,而不是断言您正在使用预期的记录。

    如果您确实需要重置 AUTO_INCREMENT 计数器,请改用 :truncation 清理策略。 IE。删除clean_with 行并将策略设置为:truncation。虽然它比事务慢得多。

    【讨论】:

    • DatabaseCleaner.clean_with(:truncation, pre_count: true, reset_ids: true) 配置使用截断,不是吗??
    • 是的,但是clean_with 会在调用它的地方立即清理数据库,即在您的案例中的所有测试之前清理一次。但 AUTO_INCREMENT 不会在每次测试后重置。
    • 好的...我不明白。那么更好的是,在 teardown 方法中调用 clean_with(:truncation...) ,或者将策略更改为 :truncation ?有什么区别?
    • 实际上可能大致相同,但标准方法是设置策略。 IE。删除clean_with 行并将策略设置为:truncation。应该就是这样。
    猜你喜欢
    • 2021-11-14
    • 2012-02-04
    • 2016-10-10
    • 1970-01-01
    • 1970-01-01
    • 2013-06-11
    • 2015-04-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多