I have a silly “queue-class[1]” with the following method, that I want to spec out with Rspec. I am not interested in testing if writing to the file-system works (It works, my computer works) but in whether or not the correct data gets written away.
def write transaction
File.open("messages/#{@next_id}", "w") {|f| f.puts transaction }
@next_id += 1
end
The spec for testing this is:
describe TransactionQueue do
context "#write" do
it "should write positive values" do
open_file = mock File
open_file.stub(:puts)
File.any_instance.stub(:open).and_yield(open_file)
File.any_instance.should_receive(:open)
open_file.should_receive(:puts).with("+100")
@queue = TransactionQueue.new
@queue.write("+100")
end
end
end
Running this, fails, because my Mocks never receive the expected “open” and “puts” messages.
Can I mock File this way? Did I use the any_instance correctly; is my attempt to stub a “block-yield” correct?
I’d rather not use extra gems like FakeFS when it can be avoided; this is not so much about getting it to work; bu mostly about actually understanding what is going on. Hence my attempt to avoid extra gems/layers of complexity.
[1] Class is from The Cucumber Book; but these tests have littel to do with Cucumber itself. I somehow broke the code when following the book; and want to find out what, by writing unit-tests for the parts that the book does not write tests for: the helper classes.
It’s not “any instance” of the
Fileclass that you expect to receive theopenmethod; it’s theFileclass itself:Furthermore, don’t use both a stub and an expectation. If you want to verify that
File.openis actually called:If you merely want to stub the
openmethod in case it gets called, but don’t want to require it as behaviour of the@queue.writemethod:(This is from memory, I haven’t used RSpec for a few months.)