diff options
author | Jeremy Wadsack <jeremy.wadsack@gmail.com> | 2015-06-28 15:11:34 -0700 |
---|---|---|
committer | Jeremy Wadsack <jeremy.wadsack@gmail.com> | 2016-07-12 23:35:29 -0700 |
commit | 31a8588a01cf5aadb864f609efad6ee24b5d4055 (patch) | |
tree | 6d5929b7d83782b51650c0a548362656b2c11f84 /activerecord/test/cases | |
parent | fc50f1fd50b05dc7e0f259dbe840e6d292e85aef (diff) | |
download | rails-31a8588a01cf5aadb864f609efad6ee24b5d4055.tar.gz rails-31a8588a01cf5aadb864f609efad6ee24b5d4055.tar.bz2 rails-31a8588a01cf5aadb864f609efad6ee24b5d4055.zip |
Create connection.active_record notification and use that to ensure that lazy-
loaded model classes have their connections wrapped in transactions.
See #17776
In Rails 4 config.eager_load was changed to false in the test environment. This
means that model classes that connect to alternate databases with
establish_connection are not loaded at start up. If use_transactional_fixtures
is enabled, transactions are wrapped around the connections that have been
established only at the start of the test suite. So model classes loaded later
don't have transactions causing data created in the alternate database not to
be removed.
This change resolves that by creating a new connection.active_record
notification that gets fired whenever a connection is established. I then added
a subscriber after we set up transactions in the test environment to listen for
additional connections and wrap those in transactions as well.
Diffstat (limited to 'activerecord/test/cases')
-rw-r--r-- | activerecord/test/cases/connection_pool_test.rb | 12 | ||||
-rw-r--r-- | activerecord/test/cases/fixtures_test.rb | 40 |
2 files changed, 52 insertions, 0 deletions
diff --git a/activerecord/test/cases/connection_pool_test.rb b/activerecord/test/cases/connection_pool_test.rb index 09e7848bda..2bdabaee62 100644 --- a/activerecord/test/cases/connection_pool_test.rb +++ b/activerecord/test/cases/connection_pool_test.rb @@ -341,6 +341,18 @@ module ActiveRecord end end + def test_connection_notification_is_called + payloads = [] + subscription = ActiveSupport::Notifications.subscribe('!connection.active_record') do |name, started, finished, unique_id, payload| + payloads << payload + end + ActiveRecord::Base.establish_connection :arunit + assert_equal [:class_name, :config, :connection_id], payloads[0].keys.sort + assert_equal 'primary', payloads[0][:class_name] + ensure + ActiveSupport::Notifications.unsubscribe(subscription) if subscription + end + def test_pool_sets_connection_schema_cache connection = pool.checkout schema_cache = SchemaCache.new connection diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index 9455d4886c..a06aa4b247 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -622,6 +622,46 @@ class TransactionalFixturesOnCustomConnectionTest < ActiveRecord::TestCase end end +class TransactionalFixturesOnConnectionNotification < ActiveRecord::TestCase + self.use_transactional_tests = true + self.use_instantiated_fixtures = false + + def test_transaction_created_on_connection_notification + connection = stub(:transaction_open? => false) + connection.expects(:begin_transaction).with(joinable: false) + fire_connection_notification(connection) + end + + def test_notification_established_transactions_are_rolled_back + # Mocha is not thread-safe so define our own stub to test + connection = Class.new do + attr_accessor :rollback_transaction_called + def transaction_open?; true; end + def begin_transaction(*args); end + def rollback_transaction(*args) + @rollback_transaction_called = true + end + end.new + fire_connection_notification(connection) + teardown_fixtures + assert(connection.rollback_transaction_called, "Expected <mock connection>#rollback_transaction to be called but was not") + end + + private + + def fire_connection_notification(connection) + ActiveRecord::Base.connection_handler.stubs(:retrieve_connection).with(Book).returns(connection) + message_bus = ActiveSupport::Notifications.instrumenter + payload = { + class_name: 'Book', + config: nil, + connection_id: connection.object_id + } + + message_bus.instrument('!connection.active_record', payload) {} + end +end + class InvalidTableNameFixturesTest < ActiveRecord::TestCase fixtures :funny_jokes # Set to false to blow away fixtures cache and ensure our fixtures are loaded |