2

I've searched far and wide and I hope someone can answer this question. I'm using the following code to stub out the 'exists?' method for FileTest in an rspec spec:

it "returns no error if file does exist" do
  @loader = MovieLoader.new
  lambda {
    FileTest.stub!(:exists?).and_return(true)
    @loader.load_file
  }.should_not raise_error("File Does Not Exist")
end

What I really want to do is to ensure that the existence of a very specific file is stubbed out. I was hoping something like this would do the job:

it "returns no error if file does exist" do
  @loader = MovieLoader.new
  lambda {
    FileTest.stub!(:exists?).with(MovieLoader.data_file).and_return(true)
    @loader.load_file
  }.should_not raise_error("File Does Not Exist")
end

However, this doesn't seem to be working. I am having a very difficult time finding documentation on what the 'with' method actually does. Perhaps I'm barking up the wrong tree entirely.

Can someone please provide some guidance?

Agazoom
  • 618
  • 4
  • 19
  • What's the failure message you're getting? – David Chelimsky Feb 12 '12 at 13:46
  • Hi David .. sorry, but I didn't see your response earlier. I was not getting a failure message. I just couldn't figure out how to write the test in a manner to check for a specific file. I reorganized my tests to make it work. Thanks. – Agazoom Feb 13 '12 at 06:15

1 Answers1

2

The RSpec stubbing framework leaves a bit to be desired, and this is one of those things. The stub!(:something).with("a thing") ensures that each time the something method is called that it receives "a thing" as the input. If it receives something other than "a thing", RSpec will stop the test and report an error.

I think you can achieve what you want, you'll just have to approach this a little differently. Instead of stubbing out FileTest, you should be stubbing out a method on your @loader instance, and that method would normally call FileTest.exists?. Hopefully this demonstrates what I'm getting at:

class MovieLoader
  def load_file
    perform_loading if file_exists?(file_path)
  end

  def file_exists?(path)
    FileTest.exists? path
  end
end

Your test would then look like:

it "returns no error if file does exist" do
  @loader = MovieLoader.new
  lambda {
    @loader.stub!(:file_exists?).with(MovieLoader.data_file).and_return(true)
    @loader.load_file
  }.should_not raise_error("File Does Not Exist")
end

Now you are only stubbing one instance of the loader, so other instances will not inherit the stubbed version of file_exists?. If you need to be more fine-grained than that, you'll probably need to use a different stubbing framework, which RSpec supports (stubba, mocha, etc).

siannopollo
  • 1,464
  • 11
  • 24
  • What would you using mocha that you can't do with rspec-mocks? – David Chelimsky Feb 12 '12 at 13:46
  • Thanks for the response. Do you mean that in my version of the stub, FileTest.stubs! is being stubbed out entirely for all tests? (I'm a newbie to all this, so forgive if I'm asking an obvious question). – Agazoom Feb 12 '12 at 17:28
  • @DavidChelimsky I wasn't suggesting that those libraries could achieve what the OP wanted, just that he could try them and see what they could offer him. I've personally never used mocha or stubba, but know people who have and like them. – siannopollo Feb 12 '12 at 22:02
  • @Agazoom When you stub FileTest out in an example, every time that method is called *during that example* the method will be stubbed out. RSpec resets all stubs that were created during an example, so FileTest will behave normally in the all other examples unless you stub it again. I believe the only exception to that is stubs created in a `before :all` block. – siannopollo Feb 12 '12 at 22:05
  • Thanks for the comments. I think I've come up with a strategy that works. – Agazoom Feb 13 '12 at 01:12