首页 > 解决方案 > 在 rspec 中设置 RAILS_ENV

问题描述

请考虑以下代码:

class MyModel
  validate my_validation unless ENV["RAILS_ENV"] == "test" 
end

我们有一个将对测试套件的巨大部分产生重大影响的验证。我只希望它在 prod 中执行,而不是在运行测试套件时执行* ...除了有关此验证的实际测试。

因此,在测试验证时,我需要将其设置ENV["RAILS_ENV"]为其他内容,然后进行测试。我在我的my_model_spec.rb-file 中尝试了这个:

it "tests the validation" do
  ENV["RAILS_ENV"] = "development"
  
  # Tests the validation..
  
  ENV["RAILS_ENV"] = "test"
end

这会在规范文件中设置变量,但在其中进行检查my_model.rb的地方ENV["RAILS_ENV"]仍然返回“测试”。

有没有办法实现ENV["RAILS_ENV"]SPEC 文件中的声明,并且在示例运行期间执行模型代码时仍然设置该声明?


标签: rubyrspec

解决方案


强制性:

validate my_validation unless ENV["RAILS_ENV"] == "test" 

在 99.9% 的情况下,这确实不是一个好主意。

只是觉得我需要说清楚,以防未来的读者看到这篇文章并得到有趣的想法......(最好更新测试套件以保持有效,例如通过更改工厂。)

有没有办法实现ENV["RAILS_ENV"]SPEC 文件中的声明

是的 - 你可以存根值:

allow(ENV).to receive(:[]).with('RAILS_ENV').and_return('development')

您还可以考虑其他一些方法。

例如,为什么不直接调用方法来运行这个测试呢?

record = MyModel.new # or using FactoryBot.build / whatever
record.my_validation

或者,您可以添加一个模型属性来强制运行验证:

class MyModel
  attr_accessor :run_my_validation
  validate my_validation if ENV["RAILS_ENV"] != "test" || run_my_validation
end

# and in the test:
record = MyModel.new # or using FactoryBot.build / whatever
record.run_my_validation = true
expect(record.valid?).to be_true

您可以考虑的另一种方法是,从生产代码中消除 rails 环境检查,将设置一个特定于环境的配置值。同样,您可以在规范中存根:

class MyModel
  validate my_validation if Rails.configuration.run_my_model_validation
end

# and in the test:
allow(Rails.configuration).to receive(:run_my_model_validation).and_return(true)

上述的另一个好处是您可以在开发模式下启用验证,而无需对应用程序进行任何代码更改。


推荐阅读