문제

사용하는 프로젝트에 대한 테스트를 어떻게 작성합니까? establish_connection 다른 데이터베이스에 연결하는 모델에서?

도움이 되었습니까?

해결책

특정 모델이 다른 데이터베이스에 연결하기 위해 설립 할 때, 테이블을 테스트하는 동안 직면하는 문제 중 하나는 생성 된 테스트 데이터가 자동으로 롤백되지 않는다는 것입니다.

트랜잭션 저장 포인트를 생성하고 테스트에 대한 데이터를 롤백하는 실제 코드 rails/activerecord/lib/active_record/fixtures.rb. 특히 두 가지 방법이 있습니다 setup_fixtures 그리고 teardown_fixtures. 이러한 방법의 코드는 간단합니다. 그들은 단지 SavePoint를 만들고 각 테스트에 대해 롤백을합니다. 그러나 그것은 단지 만 수행합니다 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

다른 팁

동일한 모델 기능을 여전히 테스트하므로 모델에 Spe란L_Connection을 배치 한 후 테스트 코드를 변경할 필요가 없습니다.

ActiveRecord 메소드로서 Speque_Connection 방법을 테스트 할 필요가 없으며 출시 전에 잘 테스트됩니다.

여전히 그렇게하려면 다른 메소드 내에서 메소드를 호출하고 해당 DB의 적절한 테이블에 연결할 수 있는지 확인하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top