更改测试过程中的Rails环境

42

如何在Rails测试中更改环境变量


这可能是一个非常糟糕的想法。 - Steven Soroka
5个回答

80

你可以这样做

Rails.stub(env: ActiveSupport::StringInquirer.new("production"))

然后Rails.envRails.development?等将按预期工作。

使用RSpec 3或更高版本时,您可能希望使用新的“零猴子补丁”语法(如@AnkitG在另一个答案中提到)以避免弃用警告:

allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new("production"))

我通常在spec helper中定义一个stub_env方法,这样我就不必在我的测试中行内输入所有内容。

可以考虑一种选择(如在此处评论中建议的),即依靠一些更有针对性的配置,您可以在环境文件中设置并在测试中进行更改。


51
谢谢自己!我发现这篇文章并准备点赞,然后注意到它是我6个月前写的... - Henrik N
这是一个好答案。我也认为在代码中到处都有Rails.env或Rails.development?通常是不好的,但这帮助我为一些遗留代码添加了测试覆盖率。 - fregas
10
你可以使用'production'.inquiry代替 ActiveSupport::StringInquirer.new('production')(参见String#inquiry - epidemian
在加入调试器并运行 Rails.env 后,我得到了正确指定的环境,但我的应用程序仍然在错误的环境下运行(通过测试我的环境变量可以确定)。有任何想法为什么会这样? - Noam Hacker
@NoamHacker,这听起来像是一个非常危险的想法!? - hatenine
显示剩余7条评论

19

自 Rspec 3 开始,您可以执行以下操作:

it "should do something specific for production" do 
  allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new("production"))
  #other assertions
end

1
谢谢您发布这个内容,这是适用于RSpec >= 3的更好的语法。 - Chris Hough
我在这个语句后面添加了一个调试器,但是当测试我的环境变量时,我仍然从错误的环境中获取它们 - 而不是语句中指定的那个。有什么建议吗? - Noam Hacker
@NoamHacker 你用的是什么调试器?puts Rails.env 输出了什么? - AnkitG
@AnkitG,感谢您的回复。我正在使用byebug,并且Rails.env给出了“production”。但是,如果我尝试使用ENV['MY_VARIABLE'],它将给我一个测试版本而不是生产版本。 - Noam Hacker

9
有时返回一个不同的环境变量可能会很麻烦(需要生产环境变量,警告信息等)。根据您的情况,作为替代方案,您可以简单地返回您需要的值,让测试认为它在另一个环境中。例如,如果您希望Rails相信自己在生产环境中,以检查Rails.env.production?的代码,您可以像这样做:
it "does something specific when in production" do 
  allow(Rails.env).to receive(:production?).and_return(true)
  ##other assertions
end

你可以对其他环境进行相同的操作,例如 :development?:staging?等。如果你不需要返回完整环境的全部功能,则这可能是另一个选项。

简单又优美 - 谢谢! - house9
对于我的使用情况,我只希望第二次调用 Rails.env.production? 为 true,因为第一次调用需要为 WebMock 的 false,所以我选择了 allow(Rails.env).to receive(:production?).and_return(false, true).twice - HarlemSquirrel

0
作为对上面几个答案的简化变体,以下代码对我有效:
allow(Rails).to receive(:env).and_return('production')

或者,像我在shared_examples中所做的那样,将其作为变量传递:

allow(Rails).to receive(:env).and_return(target_env)

我怀疑这不足以解决...StringInquirer...的问题,因为您的应用程序使用其他方法来检查环境(例如env.production?),但如果您的代码只是要求Rails.env,那么这将更易读。结果可能会有所不同。


-3
如果你正在使用像rspec这样的东西,你可以stub Rails.env来返回一个不同的值,以便针对你正在运行的特定测试示例:
it "should log something in production" do
  Rails.stub(:env).and_return('production')
  Rails.logger.should_receive(:warning).with("message")
  run_your_code
end

2
因为它只能进行字符串比较才能正常工作。不能像“本地”一样使用,例如以下代码无法正常工作:Rails.env.production? - John Hinnegan
我在Rails 3.2中使用Rails.stub(:env)时遇到了困难。不确定原因。 - fregas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接