【问题标题】:Fake an active record model without db伪造没有数据库的活动记录模型
【发布时间】:2011-09-28 16:57:26
【问题描述】:

我觉得我错过了一些东西。我正在编写一个 ruby​​ gem,它允许与活动记录交互作为其主要功能的附加。

在为其编写测试用例时,我需要能够指定虚拟活动记录模型来测试此功能。如果我能得到一个不需要任何与数据库连接的活动记录模型的实例,它可能有关系,所有这些东西,但不需要我在数据库中设置表,那将是极好的。我对测试还很陌生,在 Rails 测试之外我还很新,但似乎我应该能够相当容易地做类似的事情,但我什么也没找到。

谁能告诉我我错过了什么?我看过工厂、制造商、固定装置,所有这些似乎都想打数据库。人们如何在您只需要 AR 对象进行测试的情况下测试 gem?

【问题讨论】:

    标签: ruby testing activerecord gem


    【解决方案1】:

    听起来你需要NullDB:

    NullDB 是应用于 ActiveRecord 数据库适配器的 Null Object 模式。它是一个数据库后端,可将数据库交互转换为无操作。使用 NullDB,您可以测试您的模型业务逻辑 - 包括 after_save 挂钩 - 无需接触真实的数据库。

    【讨论】:

    • 这正是我想要的。谢谢!
    • 这个库的一个缺点是它与 Rspec 的耦合方式。如果您不使用 Rspec,请记住一些事项
    【解决方案2】:

    其他人也遇到了同样的问题。我通常的做法是使用模拟库进行单元测试,并使用固定装置编写一些功能性的库来补充它们以适应过于复杂而无法模拟的设置(你应该避免任何方式)。

    或者使用提供相同界面但不需要数据库的 AR 替换库。我已经有一段时间没有使用过导轨了,但曾经有一些可用。这并非完全没有与首先使用数据库相同的问题,因为这些库通常有其他要求(如 Web 服务、LDAP 等),或者只需要与模拟相同的单记录设置工作。

    或者咬紧牙关,只使用固定装置,但通过使用内存中的 sqlite DB 仅用于测试和适当的迁移,使它们的成本非常低。

    【讨论】:

    • 你说得很好。一个小的 sqlite 数据库将是一个不错的选择。
    【解决方案3】:

    是的,我想在 Rails 2.3 中执行此操作,这让我很头疼。我认为现在使用 ActiveModel 会更容易,它为您提供了一个明确的界面,如果您想自己动手。

    另外,我自己还没有使用过它,但是 Josh Susser 有一个宝石,可以让你将 AR 风格的行为混合到任何类中。它似乎适合在表单中使用普通的 ruby​​ 对象,但它也可能对单元测试有用。见informal

    他在最近的 Ruby Rogues episode 中谈到了它

    【讨论】:

    • 非正式看起来真的很酷。我实际上可能会将它用于其他用途,感谢您指出这一点。
    【解决方案4】:

    另一种选择是使用 sqlite3 适配器并在内存中运行数据库,并在测试后使用 DatabaseCleaner 清除记录。

    这种方法有一定的优势:

    • 可以看到测试中的SQL,简化了查询优化过程
    • 接近“现实生活”的例子

    另一方面,我应该说它有点凌乱,因为它有点长,但可以随意重组它;)

    以下是您需要的简要说明:

    # 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
    

    【讨论】:

      猜你喜欢
      • 2012-11-30
      • 1970-01-01
      • 2016-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-29
      相关资源
      最近更新 更多