我的应用程序访问远程数据库。 如何有效地运行unit testing?

我有一个配置,除了本地postgresql数据库,我的Rails应用程序还访问远程AWS数据库。 我的问题是,即使在不涉及远程数据库的测试中,应用程序每次都建立与远程数据库的连接,因此我的测试运行起来很懒散。

是否有一种干净的方法来禁用对不需要它的rspec测试的远程数据库服务器的访问? (并为那些需要它的测试启用它?)

我能想到的最好的是将我的rspec测试划分为两个独立的部分 – 那些不需要访问远程数据库和那些部分 – 并使用环境变量来相应地启用或禁用部分config / database.yaml 。

为了清楚起见,我的config/database.yaml文件包含(部分):

 # file: config/database.yaml # Define connections to the external database remote: adapter: mysql database: remote username:  password:  host: awsserver-production-mysql.abcdef1234567890.us-west-2.rds.amazonaws.com port: 3306 test: adapter: postgresql encoding: unicode database: MyApp_test pool: 5 username:  password:  

(注意:如果您想知道,使用模拟将无济于事:甚至在测试开始运行之前就建立了远程数据库连接。而vcr只拦截HTTP连接 – 数据库连接使用不同的机制。)

更新

我找到了如何动态建立连接的示例:

 def connect_to_myapp_database ActiveRecord::Base.establish_connection(:adapter => "mysql", :database => 'myapp', :username => ENV['MYAPP_DB_USERNAME'], :password => ENV['MYAPP_DB_PASSWORD'], :host => 'mayapp-mysql.abcdefg123456.us-west-2.rds.amazonaws.com', :port => 3306, ) end 

哪个工作正常 – 我可以使用它连接到外部数据库只是为了那些需要它的测试。 但这引出了一个问题:一旦我这样做,我如何断开与外部数据库的连接

TL; DR:使用nulldb和测试感知父类

在测试时使用nulldb,否则使用真正的db。 这是如何做:

首先,将它包含在您的Gemfile中:

 group :development, :test do gem 'activerecord-nulldb-adapter', :git => 'git://github.com/nulldb/nulldb.git' end 

然后进行通常的bundle install

为外部数据库中支持的所有模型定义基类:

 class ExternalModel < ActiveRecord::Base if Rails.app.test? establish_connection(:adapter => :nulldb) else establish_connection(:myapp) end def readonly?; true; end end 

然后所有外部模型都inheritance自ExternalModel(我应该从一开始就这样做):

 class ExternalUser < ExternalModel ... end 

在测试环境中运行时,它不会尝试连接到外部表。 当然,尝试访问ExternalUser的实例将失败,但您可以在集成测试期间选择性地与外部数据库建立连接,否则将存根或模拟对外部模型的引用。

最重要的是,我现在所有的测试都运行得非常快。