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

时间:2010-11-01 15:42:05

标签: ruby file testing rspec file-io

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

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

我想通过rspec测试这段代码。这样做的最佳做法是什么?

5 个答案:

答案 0 :(得分:56)

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

因此在您的测试代码中(假设您的SUT实例为sutObject且序列化程序名为writeStuffTo

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

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

答案 1 :(得分:46)

对于非常简单的i / o,你可以模拟文件。所以,给定:

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的答案。

答案 2 :(得分:18)

这是如何模拟文件(使用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

答案 3 :(得分:17)

您可以使用fakefs

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

您使用

进行检查
File.exists? "filename" 

如果创建了文件。

你也可以用

阅读
File.open 

并对其内容运行期望。

答案 4 :(得分:0)

对于像我这样需要修改多个目录中的多个文件的人(例如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)