ActiveRecord和Tests的奇怪行为

时间:2013-01-17 00:37:19

标签: ruby-on-rails rails-activerecord

我有两个看起来像这样的ActiveRecord模型:

class Foo < ActiveRecord::Base
  after_commit { puts 'after commit in Foo' }
end

class Bar < ActiveRecord::Base
   after_commit { puts 'after commit in Bar' }
end

然后我有两个看起来像这样的测试:

测试/单元/ foo_test.rb

class FooTest < ActiveSupport::TestCase
  setup do
    puts 'Creating Foo'
    @foo = Foo.create
 end

 should 'foo exists' do
   assert !@foo.nil?
 end
end

测试/单元/ bar_test.rb:

class BarTest < ActiveSupport::TestCase
  self.use_transactional_fixtures = false

  setup do
    pits 'Creating Bar'
    @bar = Bar.create
 end

 should 'bar exists' do
   assert !@bar.nil?
 end
end

但是当我一起运行这些测试时,我得到以下输出:

Creating Foo
Creating Bar
after commit in Foo
after commit in Bar

我的印象是,默认情况下Rails将事务中的活动记录包装在一起,然后在每次测试结束时进行回滚。我已经尝试显式设置use_transactional_fixtures = true但是没有产生任何结果。

我的问题是这里发生了什么?似乎活动记录正在为Bar创建回调链,然后在测试完成后它不会被清除。我也尝试过使用DatabaseCleaner并在测试结束时在拆解回调中明确地销毁@bar,但这些都没有用。

编辑:看起来它可能是rails中的问题:https://github.com/rails/rails/pull/3300

1 个答案:

答案 0 :(得分:1)

原来在rails中存在一个错误,导致事务中的记录即使在回滚实际数据库之后仍然存在。以下是讨论:https://github.com/rails/rails/pull/3300

如果需要,您可以使用以下方法(如github线程中所建议的)清除测试运行之间的活动事务:

def teardown_fixtures
        if run_in_transaction? && ActiveRecord::Base.connection.open_transactions != 0
    ActiveRecord::Base.connection.rollback_db_transaction

    ActiveRecord::Base.connection.send(:rollback_transaction_records, true)
    if ActiveRecord::Base.connection.instance_variable_get('@_current_transaction_records')
      ActiveRecord::Base.connection.decrement_open_transactions
    end

    ActiveRecord::Base.clear_active_connections!
  end
end