【问题标题】:running Rails unit tests without loading the environment or using a database在不加载环境或使用数据库的情况下运行 Rails 单元测试
【发布时间】:2011-08-16 14:08:06
【问题描述】:

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

我以前见过这样做,似乎人们谈论它已经足够了,但我找不到任何好的/当前资源来完成它。

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

【问题讨论】:

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


    【解决方案1】:

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

    没有数据库的测试会涉及很多模拟和存根,没有什么特别要添加的。

    【讨论】:

      【解决方案2】:

      查看NullDB。我的成功参差不齐。

      创建者和当前维护者正在寻找新的维护者,因此应该尽快解决其中的一些当前问题。

      【讨论】:

      • 看起来 NullDB 已经获得了很多关注,并且只有一个未解决的问题,似乎与 CI 配合得很好。
      【解决方案3】:

      编写应用程序的替代方法略有不同。

      将您要测试的所有重要逻辑提取到不依赖数据库的 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 的所有好处,例如将方法调用与事务包装在一起。
      不涉及其他框架或 gem - 纯 ruby​​ 和 RSpec 或您选择的测试框架:)

      【讨论】:

        猜你喜欢
        • 2012-10-14
        • 2011-04-15
        • 1970-01-01
        • 2023-01-09
        • 1970-01-01
        • 2011-08-20
        • 2021-01-14
        • 1970-01-01
        • 2016-09-24
        相关资源
        最近更新 更多