prueba y establecer_conexión
Pregunta
¿Cómo escribo pruebas para proyectos que usan establo_conexión
en el modelo para conectarse a otra base de datos?
Solución
Cuando estableces una conexión para que ciertos modelos se conecten a una base de datos diferente, uno de los problemas que enfrentarías al probar esas tablas es que los datos de prueba que creaste no se revertirán automáticamente.
El código real para crear un punto de guardado de transacción y revertir los datos para las vidas de prueba en rails / activerecord / lib / active_record / fixtures.rb
. Y especialmente hay dos métodos setup_fixtures
y teardown_fixtures
. El código en esos métodos es sencillo. Simplemente crean un punto de rescate y retroceden para cada prueba. Pero solo lo hace para la conexión ActiveRecord :: Base
.
Entonces, lo que tienes que hacer es "parche de mono" estos métodos para que, además de la conexión ActiveRecord :: Base
, se realice el mismo conjunto de operaciones para su conexión de base de datos adicional.
Aquí hay un código de muestra para el mismo:
## 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
Otros consejos
No veo la necesidad de cambiar los códigos de prueba después de que establezca establecer_conexión en su modelo, ya que todavía prueba la misma funcionalidad del modelo.
No necesitará probar el método establecer_conexión, ya que es un método activrecord y está bien probado, antes del lanzamiento.
aunque si todavía desea hacerlo, llame al método dentro de un método diferente y vea si puede conectarse a las tablas apropiadas en ese DB.