mysql - 我的应用程序访问远程数据库。如何有效地运行单元测试?

标签 mysql ruby-on-rails postgresql rspec ruby-on-rails-4

我有一个配置,除了本地 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

效果很好——我可以使用它连接到外部数据库,仅用于那些需要它的测试。但这引出了一个问题:完成此操作后,如何断开与外部数据库的连接?

最佳答案

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

测试时使用 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 的实例会失败,但您可以在集成测试期间有选择地建立与外部数据库的连接,或者对外部模型进行 stub 或模拟引用。

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

关于mysql - 我的应用程序访问远程数据库。如何有效地运行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19729840/

相关文章:

mysql - 如何通过VB将 'insert'数据存入数据库

ruby-on-rails - 异常通知 - 如何在开发中关闭。模式

ruby-on-rails - 动态创建类

Django 按子查询中注释的计数过滤

ruby-on-rails - 如何在 Rails 应用程序中使用 SQL_ASCII 编码?

sql - 是否可以取代 mysql 中的 ORDER BY 子句?

mysql - 在一个mysql查询中使用concat和group_concat函数

MySQL Visual Studio 2015 无法为所选对象创 build 计窗口

javascript - Rails AJAX 部分无需提交表单

postgresql - 如何使用多个键和值 rails 5 将数据存储在 hstore 数据类型中