Rspec: как проверить файловые операции и содержимое файла - PullRequest
41 голосов
/ 01 ноября 2010

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

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

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

Ответы [ 5 ]

57 голосов
/ 01 ноября 2010

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

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

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

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

47 голосов
/ 02 ноября 2010

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

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.

18 голосов
/ 27 ноября 2015

Вот как смоделировать файл (с 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
17 голосов
/ 07 ноября 2010

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

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

Вы проверяете с

File.exists? "filename" 

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

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

File.open 

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

0 голосов
/ 02 марта 2018

Для таких, как я, которым необходимо изменить несколько файлов в нескольких каталогах (например, генератор для Rails), я использую временную папку.

Dir.mktmpdir do |dir|
  Dir.chdir(dir) do
    # Generate a clean Rails folder
    Rails::Generators::AppGenerator.start ['foo', '--skip-bundle']
    File.open(File.join(dir, 'foo.txt'), 'w') {|f| f.write("write your stuff here") }
    expect(File.exist?(File.join(dir, 'foo.txt'))).to eq(true)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...