0

I want to test the else branch of the following ruby code:

SCHEMA_SOURCE = if File.exist? SCHEMA_FILENAME
                  SCHEMA_FILENAME
                else
                  ContentfulApi::Http
                end

I cannot find a way to mock the non-existence of the file SCHEMA_FILENAME. Here are the simplified versions of the test I have tried, and the error:

it 'fails to find file when it does not exist' do
  allow(File).to receive(:exists?).and_return(false)
  expect(File.exist?(ContentfulApi::SCHEMA_FILENAME)).to be_falsey
end
it 'fails to find file when it does not exist' do
  allow(File).to receive(:exists?).with(ContentfulApi::SCHEMA_FILENAME)\
                                  .and_return(false)
  expect(File.exist?(ContentfulApi::SCHEMA_FILENAME)).to be_falsey
end

These both fail with the error

expected: falsey value
got: true

it 'fails to find file when it does not exist' do
  File.stub(:exists?) { false }
  expect(File.exist?(ContentfulApi::SCHEMA_FILENAME)).to be_falsey
end
it 'fails to find file when it does not exist' do
  File.stub!(:exists?).with(ContentfulApi::SCHEMA_FILENAME)\
                      .and_return(false)
  expect(File.exist?(ContentfulApi::SCHEMA_FILENAME)).to be_falsey
end

These both fail with the error

undefined method `stub' for File:Class

My first two attempts follow the example in the Method Stubs documentation, though there may be a distinction between classes and objects that is not explored in that documentation. (Though classes are objects in Ruby, right?)

The second two attempts follow older documentation.

How should I stub File.exist? SCHEMA_FILENAME so that it returns false even though the file does actually exist?

N.B. The approaches in these similar questions do not work:

dumbledad
  • 16,305
  • 23
  • 120
  • 273
  • On a side note I don't think this is a good use of a constant - constants should just be straight up assignment. So if you have to write a test for it then it should not be a constant. Make it a class method instead. – max Mar 13 '22 at 11:15

1 Answers1

1

You're mocking File.exists? and calling File.exist?.

Note that if you have verify_partial_doubles set, and you should, RSpec won't allow you to mock a method which does not exist.

RSpec.configure do |config|
  config.mock_with :rspec do |mocks|
    mocks.verify_partial_doubles = true
  end
end

RSpec.describe File do
  it 'cannot mock a method whcih does not exist' do
    allow(File).to receive(:dslkfjalk).and_return(true)
  end
end
Failures:

  1) File cannot mock a method whcih does not exist
     Failure/Error: allow(File).to receive(:dslkfjalk).and_return(true)
       File does not implement: dslkfjalk

But File does have both exist? and exists? methods. File.exists? is deprecated and removed from the documentation, but I guess it still... exists.

Schwern
  • 153,029
  • 25
  • 195
  • 336