Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mock file input as file path on Rspec

I have a question on how to use rspec to mock a file input. I have a following code for the class, but not exactly know a why to mock a file input. filepath is /path/to/the/file

I did my search on Google and usually turns out to be loading the actual file instead of mocking, but I'm actually looking the opposite where only mock, but not using the actual file.

module Service
  class Signing
    def initialize(filepath)
      @config = YAML.load_file(filepath)
      raise "Missing config file." if @config.nil?
    end

    def sign()      …
    end

    private
    def which()     …
    end

  end 
end

Is it possible to use EOF delimiter for this file input mocking?

file =  <<EOF
A_NAME: ABC
A_ALIAS: my_alias
EOF
like image 423
xbeta Avatar asked Jan 23 '13 21:01

xbeta


2 Answers

You could stub out YAML.load_file and return parsed YAML from your text, like this:

yaml_text = <<-EOF
  A_NAME: ABC
  A_ALIAS: my_alias
EOF
yaml = YAML.load(yaml_text)
filepath = "bogus_filename.yml"
YAML.stub(:load_file).with(filepath).and_return(yaml)

This doesn't quite stub out the file load itself, but to do that you'd have to make assumptions about what YAML.load_file does under the covers, and that's not a good idea. Since it's safe to assume that the YAML implementation is already tested, you can use the code above to replace the entire call with your parsed-from-text fixture.

If you want to test that the correct filename is passed to load_file, replace the stub with an expectation:

YAML.should_receive(:load_file).with(filepath).and_return(yaml)
like image 172
Jim Stewart Avatar answered Sep 27 '22 21:09

Jim Stewart


If the idea is to put an expectation on something, I don't see much benefit on this approach of calling YAML.load to fake the return. YAML.load_file actually returns a hash, so instead of doing all that my suggestion would be to simply return a hash:

parsed_yaml = { 
  "somekey" => {
    "someotherkey" => "abc"
  } 
}

YAML.should_receive(:load_file).with(filepath).and_return(parsed_yaml)

As this is supposed to be a unit test and not an integration test, I think this would make more sense.

like image 37
Nicholas Pufal Avatar answered Sep 27 '22 22:09

Nicholas Pufal