简体   繁体   English

rspec 如果 Rails.env.production? 返回字符串怎么实现呢?

[英]rspec if Rails.env.production? return string how to implemented it?

And it does not work.它不起作用。 Can you help me how to write the right test for its case?你能帮我如何为它的案例编写正确的测试吗? Thanks very much.非常感谢。 #model.rb #model.rb

def driver_iq_api
  if Rails.env.production?
    'https://admin.sss/xmlpost.cfm'
  else
    'https://eeem/ws/xmlpost.cfm'
  end
end

model_spec.rb model_spec.rb

describe 'private methods' do
 context '.driver_iq_api' do
  it 'production true' do
    allow(Rails.env).to receive(:production?) {true}.and_return('https://admin.sss/xmlpost.cfm')
  end
  it 'production false' do
    allow(Rails.env).to receive(:production?) {false}.and_return('https://eeem/ws/xmlpost.cfm')
  end
 end
end

Setting Rails.env to something other than test , inside a test, is a bad idea.test Rails.env设置为test以外的内容是一个坏主意。 Whilst you may "get away with it" in this case, it could cause all sorts of weird side-effects in general, such as writing data to a non-test database.虽然在这种情况下您可能会“侥幸逃脱”,但通常它可能会导致各种奇怪的副作用,例如将数据写入非测试数据库。

In addition , it seems you're writing unit tests for private methods, which is typically a bad idea.此外,您似乎正在为私有方法编写单元测试,这通常是一个坏主意。 You should only normally test the public interface of a class.您通常应该只测试类的公共接口。

As stated above, this sort of config should ideally live in a configuration file, such as eg application.yml .如上所述,理想情况下,这种配置应该存在于配置文件中,例如application.yml

The other answer already shows how you could stub the behaviour, but as yet another alternative, you could consider injecting the environment as a method dependency:其他的答案已经展示了如何存根的行为,但作为另一种选择,你可以考虑注射环境作为一种方法依赖:

def driver_iq_api(env: Rails.env)
  if env.production?
    'https://admin.sss/xmlpost.cfm'
  else
    'https://eeem/ws/xmlpost.cfm'
  end
end

describe '#driver_iq_api' do
  it 'production env' do
    expect(model.driver_iq_api(env: 'production'.inquiry)).to eq 'https://admin.sss/xmlpost.cfm'
  end
  it 'test env' do
    expect(model.driver_iq_api(env: 'test'.inquiry)).to eq 'https://eeem/ws/xmlpost.cfm'
  end
end

Note that for example, 'test'.inquiry returns a ActiveSupport::StringInquirer instance - which is the same behaviour as calling Rails.env .请注意,例如, 'test'.inquiry返回一个ActiveSupport::StringInquirer实例 - 这与调用Rails.env行为相同。

...But to reiterate my original point, I wouldn't bother testing this method at all. ...但重申我原来的观点,我根本不会费心测试这种方法。

I agree you should pull this out into config since it is static, but to answer your question:我同意您应该将其提取到配置中,因为它是静态的,但要回答您的问题:

it "when production" do
  allow(Rails.env).to receive(:production?).and_return(true)
  expect(my_class.send(:driver_iq_api)).to eq('https://admin.sss/xmlpost.cfm')
end

As for you test, I'm not familiar with the receive...{block} syntax you use, and I doubt seriously that tests what you think it is testing.至于你的测试,我不熟悉你使用的receive...{block}语法,我严重怀疑测试你认为它正在测试的内容。

Here is a test suite that tests much more succinctly, and is super easy for anyone to read:这是一个测试套件,它的测试更加简洁,任何人都非常容易阅读:

describe '.driver_iq_api' do
  subject { MyModel.driver_iq_api }

  context 'when in production' do
    allow(Rails.env).to receive(:production?).and_return(true)
    it { is_expected.to eq 'https://admin.sss/xmlpost.cfm' }
  end

  context 'when not in production' do
    it { is_expected.to eq  'https://eeem/ws/xmlpost.cfm' }
  end
end

And to reinforce what @Tom Lord said, this approach is dangerous for methods that actually do things like write to databases and such.为了加强@Tom Lord 所说的,这种方法对于实际执行诸如写入数据库等操作的方法是危险的。 I'd use this only for the type of method you have in your example...returning a resource name, boolean, etc. based on env.我只会将它用于示例中的方法类型……基于 env 返回资源名称、布尔值等。 If your platform-sensitive code is buried deep in a method and can't be tested in isolation, then refactor it out of the big method into an atomic method that can easily be tested (and mocked!).如果您的平台敏感代码深埋在方法中并且无法单独测试,那么将其从大方法中重构为易于测试(和模拟!)的原子方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM