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

发布于 2024-11-29 13:54:38 字数 156 浏览 1 评论 0原文

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

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

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

As something of an academic exercise, I thought I'd try to get my unit tests running without loading the Rails env (or hitting the database).

I've seen this done before, and it seems like folks talk about it enough, but I can't find any good/current resources on getting it done.

Does anyone have any good stories or a nice long blog post about how to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

自此以后,行同陌路 2024-12-06 13:54:38

一个有用的链接:在没有 Rails 的情况下测试 Rails

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

An useful link: testing Rails without Rails

Testing without database would involve much mocks & stubs, nothing special to add.

夜声 2024-12-06 13:54:38

查看 NullDB。我在这方面取得了好坏参半的成功。

创作者&当前的维护者正在寻求新的维护者加入,因此当前的一些问题应该很快就能得到解决。

Check out NullDB. I've had mixed success with it.

The creator & current maintainer are looking to get a new maintainer in so some of its current issues should be ironed out soon.

狼性发作 2024-12-06 13:54:38

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

将您想要测试的所有重要逻辑提取到 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 或您选择的测试框架:)

Alternative approach to write application little bit differently.

Extract all important logic you want to test into ruby classes without database dependencies.
Write tests for those classes only - your tests will fly! :)

For example

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

Extract "business logic" out of database dependencies

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

Now the module CalculateNewOrderTotal can be fully covered with very fast tests which doesn't require mocks or actual database.

You can still write happy path tests with actual database for Customer.create_order method.

Extra benefits

Your business logic is independent of persistence framework.
Your business logic is independent of persistence schema, you can change how to store data without "touching" important business logic code.
No mocks involved
No extra layers of abstractions - you can still use all benefits of the ActiveRecord, for example wrap call of the method with the transaction.
No other frameworks or gems are involved - pure ruby and RSpec or testing framework of your choice :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文