【问题标题】:How do I completely avoid using a database in RSpec tests?如何完全避免在 RSpec 测试中使用数据库?
【发布时间】:2017-02-03 18:13:58
【问题描述】:

我想使用 FactoryGirl 来构建模型的内存存根,然后让所有 ActiveRecord 查询仅针对那些运行。例如:

# Assume we start with an empty database, a Foo model, 
# and a Foo factory definition.

#foo_spec.rb
stubbed_foo = FactoryGirl.build_stubbed(:foo)

# Elsewhere, deep in the guts of application
Foo.first() # Ideally would return the stubbed_foo we created
            # in the test. Currently this returns nil.

解决方案可能是使用内存数据库。但是上述情况可能吗?

【问题讨论】:

  • 如果您没有任何表,那么模型就没有要遵循的架构,因此您的存根模型可以像任何对象一样运行,而不必与生产中存在的实际架构匹配。这可能是个坏主意。你为什么要以这种方式绕过 ActiveRecord?
  • 你可以用灯具代替工厂女孩
  • @trueinViso 我不认为fixtures能解决我的问题,因为Foo类在调用first()或任何其他查询方法时仍然会进入数据库。

标签: rails-activerecord factory-bot ruby-on-rails-5 rspec3 rspec-mocks


【解决方案1】:

如果您避免使用数据库的原因是为了加快测试速度,那么还有更好的方法。

尽可能使用FactoryGirl.build,而不是create。只要您的代码不会从数据库中获取记录,这就会起作用。这适用于结构良好的代码的单元测试。 (例如,它有助于使用Service Objects 并对它们进行独立的单元测试。

对于实际需要从数据库读取的测试(如在您的 Foo.first 示例调用中),您可以使用 FactoryGirl.create 并使用事务夹具。这会在每个测试示例的开头创建一个数据库事务,然后在示例结束时回滚该事务。当您在 ActiveRecord 模型(例如 after_commit)中使用回调时,这可能会导致问题。

如果您在模型中使用after_commit 或其他需要关闭数据库事务的回调(或者您在代码中使用显式事务),我建议设置DatabaseCleaner。下面是一个配置和使用它的例子:https://gist.github.com/RobinDaugherty/9f4e5f782d9fdbe191a23de30ad8b539

【讨论】:

  • 是的,我的动机是保持测试套件的速度。我尽可能多地使用FactoryGirl.buildFactoryGirl.build_stubbed,但我一直在寻找一种完全消除数据库依赖性的方法。我认为事务性固定装置也不会完成我想要的。这可能是我过早优化的一个例子,但我只是想确保在我开始编写与数据库交互的测试之前这是不可能的。
  • 我怀疑你会看到从FactoryGirl.build 到使用存根的速度有任何显着提高。但是你肯定会在测试中失去质量,因为使用模型工厂可以确保模型行为是正确的。我不会推荐它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-15
  • 1970-01-01
  • 2018-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多