ruby-Rspec:如何测试文件操作和文件内容

在我的应用程序中,我有这样的代码:

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

我想通过rspec测试此代码。 最佳做法是什么?

petRUShka asked 2020-08-04T19:46:09Z
5个解决方案
57 votes

我建议为此使用sutObject,并确保您的SUT接受要写入的流而不是文件名。 这样,可以使用不同的文件或输出(更可重用),包括字符串IO(适合测试)

So in your test code (assuming your SUT instance is sutObject and the serializer is named writeStuffTo:

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

字符串IO的行为类似于打开的文件。 因此,如果代码已经可以使用File对象,那么它将使用StringIO。

Danny Staple answered 2020-08-04T19:47:33Z
47 votes

对于非常简单的I / O,您可以仅模拟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的答案。

Wayne Conrad answered 2020-08-04T19:48:02Z
18 votes

这是模拟File(使用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
Eduardo Santana answered 2020-08-04T19:48:22Z
17 votes

您可以使用fakefs。

它存根文件系统并在内存中创建文件

您检查

File.exists? "filename" 

如果文件已创建。

您也可以阅读

File.open 

并对其内容进行预期。

mehowte answered 2020-08-04T19:49:03Z
0 votes

对于像我这样需要修改多个目录中多个文件的人(例如,Rails的生成器),我使用temp文件夹。

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)
lulalala answered 2020-08-04T19:49:23Z
translate from https://stackoverflow.com:/questions/4070422/rspec-how-to-test-file-operations-and-file-content