Prüfung und establish_connection
Frage
Wie kann ich schreiben Tests für Projekte, die establish_connection
in Modell verwenden, um eine andere Datenbank zu verbinden?
Lösung
Wenn Sie establish_connection für bestimmte Modelle tun in eine andere Datenbank zu verbinden, von dem Problem würde stehen Sie während die Tabellen testen, dass die Testdaten Sie werden nicht automatisch zurückgerollt werden erstellt.
Der eigentlichen Code, um eine Transaktion speichert Punkt zu erstellen und die Daten rückgängig zu machen für den Test in rails/activerecord/lib/active_record/fixtures.rb
lebt. Und vor allem gibt es zwei Methoden setup_fixtures
und teardown_fixtures
. Der Code in diesen Verfahren sind geradlinig. Sie schaffen nur einen Speicherpunkt und ist für jeden Test ein Rollback. Aber es funktioniert nur für die ActiveRecord::Base
Verbindung.
Also, was Sie tun müssen, ist „Affe Patch“ diese Methoden, so dass neben der ActiveRecord::Base
Verbindung, die gleiche Menge von Operationen für die zusätzliche Datenbankverbindung fertig sind.
Hier ist ein Beispielcode für das gleiche:
## 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
Andere Tipps
Ich sehe keine Notwendigkeit, die Testcodes zu ändern, nachdem Sie establish_connection in Ihrem Modell platzieren, da Sie immer noch die gleiche Modell Funktionalität testen.
Sie werden nicht die establish_connection Methode testen müssen, als eine activrecord Methode und gut getestet wird, vor der Freigabe.
obwohl, wenn Sie immer noch so tun wollen, die Methode in einem anderen Verfahren nennt, und sehen, ob Sie zu entsprechenden Tabellen in dieser DB verbinden kannst.