私のアプリにはそのようなコードがあります:
File.open "filename", "w" do |file|
file.write("text")
end
このコードをrspecでテストしたいと思います。これを行うためのベストプラクティスは何ですか?
このためにStringIO
を使用し、 [〜#〜] sut [〜#〜] がファイル名の代わりに書き込むストリームを受け入れることを確認することをお勧めします。このように、文字列IO(テストに適しています)を含む、さまざまなファイルまたは出力を使用できます(より再利用可能)
したがって、テストコードでは(SUTインスタンスがsutObject
で、シリアライザーの名前がwriteStuffTo
であると仮定します。
testIO = StringIO.new
sutObject.writeStuffTo testIO
testIO.string.should == "Hello, world!"
String IOは開いているファイルのように動作します。したがって、コードがFileオブジェクトで既に動作できる場合、StringIOで動作します。
非常にシンプルな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の回答を好むべきです。
これは、ファイル(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
fakefs を使用できます。
ファイルシステムをスタブ化し、メモリ内にファイルを作成します
確認する
File.exists? "filename"
ファイルが作成された場合。
次のように読むこともできます
File.open
その内容に期待をかけます。
複数のディレクトリ内の複数のファイルを変更する必要がある私のような人(例えば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)