1

I have a function with several File.exists? calls:

def create(one_filename, other_filename)
    raise Error, "One error" if File.exists?(one_filename)
    raise Error, "Other error" unless File.exist?(other_filename)
    .....
end

But I don't know the way to stub the second error. The spec is something as:

it "should not create an existing file" do
    File.stub(:exists?).and_return(true)
    expect {
        subject.create('whatever')
    }.to raise_error("One error")
    end
it "should has to exists the other filename" do
    File.stub(:exists?).and_return(false)
    expect {
        subject.create('whatever.yaml')
    }.to raise_error("Other error")
end

For the second spec (it "should has to exists the other filename") the File exists? stub raises the first check.

What is the best way to spec the two raises?

John Fadria
  • 1,863
  • 2
  • 25
  • 31

2 Answers2

3

To return multiple values for multiple calls, simply do:

File.stub(:exists?).and_return(false, true)

Or, preferably, use the new syntax:

Allow(File).to receive(:exists?).and_return(false, true)

Another option would be to stub the method according to its input variables:

Allow(File).to receive(:exists?).with(one_filename).and_return(false)
Allow(File).to receive(:exists?).with(other_filename).and_return(true)

This has the added value of actually testing the behavior rather than the implementation.

Uri Agassi
  • 36,848
  • 14
  • 76
  • 93
  • It's still coupled to the implementation, the test would fail if you replace `File.exists?(one_filename)` with `Kernel.test('e', one_filename)`. – Stefan Jul 08 '14 at 08:48
  • What do you propose @Stefan? – John Fadria Jul 08 '14 at 09:00
  • @JohnFadria mocks and stubs always couple your test to your implementation. This doesn't have to be a problem, you just have to be aware of it. Actually touching the filesystem is the only way to decouple your test from the implementation. – Stefan Jul 08 '14 at 09:09
  • @JohnFadria or use a gem which fakes the filesystem: https://github.com/defunkt/fakefs – Uri Agassi Jul 08 '14 at 10:15
0

Actually

Mocking calls to FileUtils or File means tightly coupling tests with the implementation.

fakefs

Just calling the following code before your stub should be enough.

allow(File).to receive(:exist?).and_call_original

source

brcebn
  • 1,571
  • 1
  • 23
  • 46