简体   繁体   中英

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

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

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. 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 .

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 .

...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.

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. I'd use this only for the type of method you have in your example...returning a resource name, boolean, etc. based on 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!).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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