Question

I think I understand that is going on here, but I'd like to make sure.

There is some code that needs unit testing with the File methods stubbed out:

temp = File.new(uri.path)
@path = Rails.root.to_s + "/tmp/" +uri.path.split("/").last
File.open(@path, "w"){|f| f.write(temp.read)} if File.exists(temp)
temp.close

The unit test has:

file = mock(File)
File.stub(:new).and_return(file)
File.stub(:open).and_return(file)
file.stub(:close)

I'm guessing the difference between File.stub and file.stub is that File.stub will stub the method on the File class, whereas file.stub (file is a mock File object) will stub any method on a File object?

Was it helpful?

Solution

Calling stub(:method) will stub the method on the object you called it on. So your call to File.stub(:new) will stub all calls to File.new (class method). The call to file.stub(:close) will stub all calls to file.close but only on the instance you called stub on

If you want to stub all calls to any instance of File you can:

  1. use any_instance
  2. or you can stub File.new to make it only return file objects with a stubbed close, like you do in:

    File.stub(:new).and_return(file)
    File.stub(:open).and_return(file)
    

Please be aware that in case 2 every call to File.new after that will return the same instance. In case that's not what you want you can always hand a block to stub, where you can provide a substitute for the stubbed metod

OTHER TIPS

Your understanding is right.

File.stub(:new)

stubs the call new on the class File

file.stub(:close)

stubs the call close on file object

In your case, you can also do

file = mock(File, :close => nil) #this will create a mocked object that responds with nil when close is called
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top