在不加载环境或使用数据库的情况下运行Rails单元测试

时间:2011-08-16 14:08:06

标签: ruby-on-rails unit-testing activerecord testunit

作为一个学术练习,我想我会尝试在不加载Rails环境(或点击数据库)的情况下运行我的单元测试。

我之前已经看过这个,看起来人们谈论它已经足够了,但我找不到任何好的/现有的资源来完成它。

有没有人有关于如何做到这一点的好故事或长篇博文?

3 个答案:

答案 0 :(得分:7)

一个有用的链接:testing Rails without Rails

没有数据库的测试会涉及很多嘲笑和存根,没什么特别的补充。

答案 1 :(得分:3)

结帐NullDB。我已经取得了不同程度的成功。

创作者&目前的维护者正在寻找一个新的维护者,所以它的一些当前问题应该尽快解决。

答案 2 :(得分:0)

编写应用程序的另一种方法。

将要测试的所有重要逻辑提取到不依赖数据库的ruby类中。
只为那些类编写测试-您的测试会成功! :)

例如

ProductQuantity = Struct.new(:product_id, :quantity)

class Customer < ActiveRecord
  def create_order(product_quantities)
    product_ids = product_quantities.map(&:product_id)
    products = Product.where(:id => product_ids).pluck(:id, unit_price).to_h

    total = product_quantities.reduce(0) do |sum, p|
      sum += p.quantity * products.fetch(p.product_id, 0)
    end

    Order.create!(:customer_id => id, :total => total)
  end
end

从数据库依赖关系中提取“业务逻辑”

class Customer < ActiveRecord
  def create_order(product_quantities)
    products = Product.where(:id => product_ids).pluck(:id, unit_price).to_h

    total = CalculateNewOrderTotal.from(products, product_quantities)

    Order.create!(:customer_id => id, :total => total)
  end
end

module CalculateNewOrderTotal
  def self.from(products, product_quantities)
    product_quantities.reduce(0) do |sum, p|
      sum += p.quantity * products.fetch(p.product_id, 0)
    end
  end
end

现在模块CalculateNewOrderTotal可以用非常快速的测试完全覆盖,而无需模拟或实际的数据库。

您仍然可以使用Customer.create_order方法的实际数据库编写快乐的路径测试。

额外好处

您的业务逻辑独立于持久性框架。
您的业​​务逻辑独立于持久性架构,您可以更改存储数据的方式,而无需“触碰”重要的业务逻辑代码。
不涉及模拟
没有多余的抽象层-您仍然可以使用ActiveRecord的所有好处,例如,将方法与事务包装调用。
不涉及其他框架或宝石-纯红宝石和RSpec或您选择的测试框架:)