我有一个配置,除了本地postgresql数据库之外,我的Rails应用程序还可以访问远程AWS数据库。我的问题是,即使在不涉及远程数据库的测试中,应用程序每次都建立与远程数据库的连接,因此我的测试运行起来很慢。
是否有一种干净的方法来禁用对不需要它的rspec测试的远程数据库服务器的访问? (并为那些需要它的测试启用它吗?)
我能想到的最好的是将我的rspec测试划分为两个独立的部分 - 那些不需要访问远程数据库和那些部分 - 并使用环境变量来启用或禁用部分配置/数据库.yaml据此。
为清楚起见,我的config/database.yaml
文件包含(部分):
# file: config/database.yaml
# Define connections to the external database
remote:
adapter: mysql
database: remote
username: <%= ENV['PRODUCTION_DB_USERNAME'] || 'root' %>
password: <%= ENV['PRODUCTION_DB_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: <%= ENV['POSTGRESQL_DB_USERNAME'] || 'MyApp' %>
password: <%= ENV['POSTGRESQL_DB_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
工作正常 - 我可以使用它连接到外部数据库,只是为了那些需要它的测试。但这引出了一个问题:一旦我这样做,我如何断开与外部数据库?
答案 0 :(得分:2)
在测试时使用nulldb,否则使用真正的数据库。方法如下:
首先,将它包含在您的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
然后所有外部模型都从ExternalModel继承(我应该从一开始就这样做):
class ExternalUser < ExternalModel
...
end
在测试环境中运行时,它不会尝试连接到外部表。当然,尝试访问ExternalUser的实例将失败,但您可以在集成测试期间选择性地与外部数据库建立连接,否则可以选择与外部模型建立连接或模拟引用。
最重要的是,我现在所有的测试都运行得很快。