我觉得我错过了一些东西。我正在编写一个ruby gem,它允许与活动记录交互作为其主要功能的附加功能。
在为它编写测试用例时,我需要能够指定虚拟活动记录模型来测试此功能。如果我能得到一个活动记录模型的实例,它不需要任何与db的连接,可能有关系,所有这些东西,但不需要我在数据库中设置表,这将是极好的。我对测试很陌生,除了测试之外我还很新,但看起来我应该能够很容易地做到这一点,但我找不到任何东西。
谁能告诉我我缺少什么?我看过工厂,制造商,固定装置,所有那些似乎想要打到数据库。人们如何测试你需要AR对象的宝石只用于测试?
答案 0 :(得分:9)
听起来你需要NullDB:
NullDB是应用于ActiveRecord数据库适配器的Null Object模式。它是一个数据库后端,可将数据库交互转换为无操作。使用NullDB可以测试模型业务逻辑 - 包括after_save挂钩 - 而无需触及真实数据库。
答案 1 :(得分:2)
其他人也遇到了同样的问题。我通常的做法是使用模拟库进行单元测试,并使用fixture来编写一些功能库来补充它们,因为设置过于复杂而无法模拟(你应该避免使用)。
或者为AR使用替换库,它提供相同的接口但不需要DB。我有一段时间没有使用过rails,但过去常常有用。这并不是完全没有与首先使用DB相同的问题,因为这些库通常具有其他要求(如Web服务,LDAP,...),或者只需要像模拟一样需要相同的单个记录设置工作。 / p>
或者咬它并且只使用灯具,但是通过使用内存sqlite DB来进行测试和正确的迁移,使它们的成本非常小。
答案 2 :(得分:2)
是的,我想在Rails 2.3中做一段时间,这是一个巨大的嘲讽头痛。我认为现在使用ActiveModel会更容易,如果你想自己动手,它会为你提供一个明确的界面。
此外,我自己没有使用它,但是Josh Susser有一个宝石,可以让你将AR-ish行为混合到任何一个类中。它似乎适合在表单中使用普通的ruby对象,但它也可能对单元测试很有用。请参阅informal。
他在最近的Ruby Rogues episode
中谈到了这一点答案 3 :(得分:1)
另一个选择是使用sqlite3适配器并在内存中运行数据库,并使用DatabaseCleaner在测试后删除记录。
这种方法有一定的优势:
另一方面,我应该说它有点乱,因为它有点长,但随意重组它;)
以下是您需要的简要说明:
# in Gemfile
gem "activerecord" #since you are dealing with activerecord
gem "database_cleaner", :group => :test
gem "sqlite3", :group => :test
我使用以下方法来保留这个东西,但欢迎你以不同的方式:
# in RAILS_ROOT/test/support/active_record.rb
require 'logger'
ActiveRecord::Base.establish_connection(
:adapter => "sqlite3", :database => ':memory:'
)
#this line will print the SQL queries right into console
ActiveRecord::Base.logger = Logger.new(STDOUT)
# in RAILS_ROOT/test/support/database_cleaner.rb
require 'database_cleaner'
DatabaseCleaner.strategy = :truncation
# or DatabaseCleaner.strategy = :trunsaction (it is up to you)
module OrmSetup
def before_setup
DatabaseCleaner.start
end
def after_teardown
DatabaseCleaner.clean
end
end
# in RAILS_ROOT/test/test_helper.rb
...
require File.expand_path("support/active_record", File.dirname(__FILE__))
require File.expand_path("support/database_cleaner", File.dirname(__FILE__))
class Test::Unit::TestCase
include OrmSetup
end
现在在你的测试中,你可以拥有像
这样的东西require 'test_helper'
class User < ActiveRecord::Base
end
class MyFancyTest < Test::Unit::TestCase
def setup
before_setup
end
def teardown
after_teardown
end
end