测试和建立连接

时间:2009-11-30 08:54:49

标签: ruby-on-rails unit-testing activerecord model-view-controller factory-bot

如何为模型中使用establish_connection连接到另一个数据库的项目编写测试?

3 个答案:

答案 0 :(得分:10)

当您为某些模型建立connect_connection以连接到不同的数据库时,您在测试这些表时遇到的一个问题是您创建的测试数据不会自动回滚。

创建事务保存点并回滚rails/activerecord/lib/active_record/fixtures.rb中的测试生命数据的实际代码。特别是有两种方法setup_fixturesteardown_fixtures。这些方法中的代码很简单。它们只是创建一个保存点,并为每个测试进行回滚。但它只适用于ActiveRecord::Base连接。

所以你要做的就是“猴子补丁”这些方法,这样除了ActiveRecord::Base连接外,还为你的附加数据库连接完成了同样的操作。

以下是相同的示例代码:

## database.yml
development:
  database: dev
test:
  database: test
#...
my_connection_development:
  database: my_connection_dev
my_connection_test:
  database: my_connection_test
#...

## my_connection_base.rb
class MyConnectionBase < ActiveRecord::Base
  establish_connection(ActiveRecord::Base.configurations["my_connection_#{RAILS_ENV}"])
  self.abstract_class = true
end

## my_model.rb
class MyModel < MyConnectionBase
end

## my_another_model.rb
class MyAnotherModel < MyConnectionBase
end

## test_case_patch.rb
module ActiveSupport
  class TestCase
    def setup_fixtures
      return unless defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
      if pre_loaded_fixtures && !use_transactional_fixtures
        raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_fixtures'
      end
      @fixture_cache = {}
      @@already_loaded_fixtures ||= {}
      # Load fixtures once and begin transaction.
      if run_in_transaction?
        if @@already_loaded_fixtures[self.class]
          @loaded_fixtures = @@already_loaded_fixtures[self.class]
        else
          load_fixtures
          @@already_loaded_fixtures[self.class] = @loaded_fixtures
        end

        ActiveRecord::Base.connection.increment_open_transactions
        ActiveRecord::Base.connection.transaction_joinable = false
        ActiveRecord::Base.connection.begin_db_transaction

        MyConnectionBase.connection.increment_open_transactions
        MyConnectionBase.connection.transaction_joinable = false
        MyConnectionBase.connection.begin_db_transaction
      # Load fixtures for every test.
      else
        Fixtures.reset_cache
        @@already_loaded_fixtures[self.class] = nil
        load_fixtures
      end
      # Instantiate fixtures for every test if requested.
      instantiate_fixtures if use_instantiated_fixtures
    end

    def teardown_fixtures
      return unless defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
      unless run_in_transaction?
        Fixtures.reset_cache
      end
      # Rollback changes if a transaction is active.
      if run_in_transaction? && MyConnectionBase.connection.open_transactions != 0
        MyConnectionBase.connection.rollback_db_transaction
        MyConnectionBase.connection.decrement_open_transactions
      end
      # Rollback changes if a transaction is active.
      if run_in_transaction? && ActiveRecord::Base.connection.open_transactions != 0
        ActiveRecord::Base.connection.rollback_db_transaction
        ActiveRecord::Base.connection.decrement_open_transactions
      end
      MyConnectionBase.clear_active_connections!
      ActiveRecord::Base.clear_active_connections!
    end
  end
end

答案 1 :(得分:0)

我认为在您的模型中放置establish_connection之后不需要更改测试代码,因为您仍然在测试相同的模型功能。

答案 2 :(得分:-2)

在发布之前,您不需要测试establish_connection方法,因为它是一个activrecord方法并经过充分测试。

虽然如果您仍想这样做,请在其他方法中调用该方法,并查看是否可以连接到该数据库中的相应表。