Home > Mobile >  Stubbing File.exists? in RSpec
Stubbing File.exists? in RSpec

Time:03-13

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:

CodePudding user response:

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.

  • Related