Подтвердить что ты не робот

Rspec: как тестировать файловые операции и содержимое файла

В моем приложении у меня такой код:

File.open "filename", "w" do |file|
  file.write("text")
end

Я хочу протестировать этот код через rspec. Каковы наилучшие методы для этого?

4b9b3361

Ответ 1

Я бы предложил использовать StringIO для этого и убедиться, что ваш SUT принимает поток для записи вместо имени файла. Таким образом, можно использовать различные файлы или выходы (более многократно используемые), включая строку IO (хорошо для тестирования)

Итак, в вашем тестовом коде (если ваш экземпляр SUT равен sutObject, а сериализатор имеет имя writeStuffTo:

testIO = StringIO.new
sutObject.writeStuffTo testIO 
testIO.string.should == "Hello, world!"

Строка IO ведет себя как открытый файл. Поэтому, если код уже может работать с объектом File, он будет работать с StringIO.

Ответ 2

Для очень простого ввода/вывода вы можете просто высмеять файл. Итак, учитывая:

def foo
  File.open "filename", "w" do |file|
    file.write("text")
  end
end

то

describe "foo" do

  it "should create 'filename' and put 'text' in it" do
    file = mock('file')
    File.should_receive(:open).with("filename", "w").and_yield(file)
    file.should_receive(:write).with("text")
    foo
  end

end

Однако этот подход падает при наличии нескольких операций чтения/записи: простые рефакторинги, которые не изменяют конечное состояние файла, могут привести к разрыву теста. В этом случае (и, возможно, в любом случае) вы должны предпочесть ответ @Danny Staple.

Ответ 3

Вы можете использовать fakefs.

Он заглушает файловую систему и создает файлы в памяти

Вы проверяете с помощью

File.exists? "filename" 

если файл был создан.

Вы также можете просто прочитать его с помощью

File.open 

и запустите ожидание его содержимого.

Ответ 4

Вот как издеваться над файлом (с rspec 3.4), поэтому вы можете писать в буфер и позже проверять его содержимое:

it 'How to mock File.open for write with rspec 3.4' do
  @buffer = StringIO.new()
  @filename = "somefile.txt"
  @content = "the content fo the file"
  allow(File).to receive(:open).with(@filename,'w').and_yield( @buffer )

  # call the function that writes to the file
  File.open(@filename, 'w') {|f| f.write(@content)}

  # reading the buffer and checking its content.
  expect(@buffer.string).to eq(@content)
end