开发者

Why would using File.open call once result in it being called 3 times according to rspec

Below you can see that I'm calling File.open only once but rspec is telling me it received it 3 times.

def self.import_file(filename)
  current_file = filename.split('/').last
  destroy_all(["filename = ?",current_file])

  unpack_format = "A#{INPUT_FILE_FORMAT.map{|element| element[1]}.join("A")}"
  debugger
  File.open(filename, 'r').each do |line|
    hash_created = create_hash(line, unpack_format).merge({:filename=>current_file})
    create(hash_created)
  end
end  

it "should delete previous records with the same filename" do
  Payrec.should_receive(:destroy_all).with(["filename = ?", "testfile.开发者_如何学Ctxt"])
  File.should_receive(:open).and_return([@file_line])
  Payrec.import_file "testfile.txt"
end

The output is

<File (class)> expected :open with (any args) once, but received it 3 times


Everybody and his dog calls File.open. I could imagine a ton of reasons why it would called: RSpec reading its config file, Rails reading its config file(s), Cucumber reading its config file, the debugger creating a temporary file, something else creating a temporary file and so on.

You should check who is calling File.open, where that call happens, what the arguments are and why that is happening.

But, this is something you will just have to deal with, when setting expectations on core methods.

Imagine, for example, you are running your specs on Rubinius. In Rubinius, the compiler is written in Ruby. It doesn't currently cache its compiled results, but it is certainly conceivable that it could cache them, and then it would naturally use File.open. Bam! Now your specs randomly break depending on whether you hit the JIT threshold or not.

Or, even worse: all of Rubinius uses arrays and symbols extensively to implement just about everything. Try setting some expectations on those!


It's far from perfect, but as a quick hack for finding out what these File.open calls are actually doing, monkey patch this in at the top of your main script:

class File
  class << self
   alias_method :old_open, :open
    def open(*args, &block)
      p args
      block ? block.call(old_open(*args)) : old_open(*args)
    end
  end
end

Whenever File.open is called, the arguments will be put to screen.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜