回答

10

當您爲某些模型建立連接以連接到不同的數據庫時,測試這些表時將面臨的一個問題是您創建的測試數據不會自動回滾。

rails/activerecord/lib/active_record/fixtures.rb中創建事務保存點並回滾測試數據的實際代碼。特別是有兩種方法setup_fixturesteardown_fixtures。這些方法中的代碼很簡單。他們只是創建一個保存點併爲每個測試執行回滾。但它僅適用於ActiveRecord::Base連接。

所以你需要做的是「猴子補丁」這些方法,除了連接ActiveRecord::Base之外,還可以爲你的額外數據庫連接完成相同的一組操作。

這裏是一個相同的示例代碼:對Rails 2.3.5

## 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 
+0

這是爲我工作,但只有當我創建並填充在測試代碼的遙控模型。如果我嘗試使用燈具,load_fixtures會在本地數據庫而不是遠程數據庫中查找表格。是否有另一個步驟允許使用establish_connection的模型的燈具?我不必使用燈具,但很想學習。 – 2011-05-12 19:38:17

+0

@Anatortoise House:老實說,我討厭燈具,從來沒有嘗試過與燈具。 Afaik,在測試套件開始之前加載Fixtures而沒有任何事務,因此在每次測試中,如果您碰巧刪除了由fixture創建的一些數據(包裹在事務中),它將在事務結束時回滾。所以這應該自動工作。 – Selva 2011-05-19 21:52:15

0

因爲您仍在測試相同的模型功能,所以在將establish_connection放入模型後,我沒有看到需要更改測試代碼。

-2

在發佈前,您不需要測試establish_connection方法,因爲它的活動記錄方法已經過很好的測試。

儘管如果您仍想這樣做,請使用其他方法調用該方法,並查看您是否可以連接到該數據庫中的相應表。