本文介绍了我的应用程序访问远程数据库.如何有效地运行单元测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个配置,除了本地的postgresql数据库,我的Rails应用程序还访问一个远程AWS数据库.我的问题是,即使在不涉及远程数据库的测试中,该应用程序也会每次都建立到远程数据库的连接,因此我的测试运行得很慢.

I have a configuration where, in addition to the local postgresql database, my Rails app also accesses a remote AWS database. My problem is that, even in tests that don't involve the remote database, the app establishes a connection to the remote database every time, so my tests run sloooooowly.

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

Is there a clean way to disable access to the remote database server for rspec tests that don't need it? (And enable it for those tests that do need it?)

我能想到的最好的方法是将我的rspec测试分为两个独立的部分-不需要访问远程数据库的部分和需要访问远程db的部分-并使用环境变量来启用或禁用config/database的部分.yaml.

The best I can think of is partition my rspec tests into two separate parts -- those that don't need to access the remote db and those that do -- and use environment variables to enable or disable parts of config/database.yaml accordingly.

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

To make this clear, my config/database.yaml file contains (in part):

# 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连接-数据库连接使用其他机制.)

(NOTE: In case you're wondering, using mocks won't help: the remote db connection is established even before the tests start to run. And vcr only intercepts HTTP connections -- database connections use a different mechanism.)

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

I've found examples of how to dynamically establish a connection:

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

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

which works fine -- I can use this to connect to the external database just for those tests that need it. But this begs the question: how do I disconnect from the external database once I've done this?

推荐答案

TL; DR:使用nulldb和可识别测试的父类

在测试时使用nulldb,否则使用真实的db.方法如下:

TL;DR: Use nulldb and a test-aware parent class

Use nulldb when you're testing and the real db otherwise. Here's how:

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

First, include this in your Gemfile:

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

,然后执行通常的bundle install

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

Define a base class for all models that are backed in the external database:

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

  def readonly?; true; end
end

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

Then all the external models inherit from ExternalModel (I should have done this from the start):

class ExternalUser < ExternalModel
  ...
end

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

When run in a test environment, it won't try to connect to the external table. Of course, attempts to access an instance of ExternalUser will fail, but you can selectively establish a connection with the external database during integration testing, or stub or mock references to the external model otherwise.

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

Most importantly, all my tests run really fast now.

这篇关于我的应用程序访问远程数据库.如何有效地运行单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-01 04:27