TL;DR
remove_const
とconst_set
(or 定数代入)を使ってFileUtils
をFileUtils::DryRun
にすり替えて、stderrに吐き出されるメッセージを確かめる。
準備
spec_helpr.rb
やモックを行う場所に以下のコードを書きます。
Object.class_eval do
RealFileUtils = FileUtils
remove_const(:FileUtils)
FileUtils = RealFileUtils::DryRun
end
FileUtils
をFileUtils::DryRun
に差し替えています。
サンプル
実装コード
今回は以下のコードをテストしてみましょう。
class Sample
def copy_gemfile
FileUtils.copy("Gemfile", "CopyGemfile")
end
end
FileUtils.copy
を使ってGemfile
というファイルをCopyGemfile
にコピーしています。
テストコード
RSpec.describe Sample do
it do
expect {
Sample.new.copy_gemfile()
}.to output("cp Gemfile CopyGemfile\n").to_stderr_from_any_process
end
end
FileUtils::DryRun
のソースを読むとstderrに出力されていることが分かったのでそのようなテストを書きます。
to_stderr_from_any_process
がポイントです。to_stderr
ではFileUtils::DryRun
の出力を捕捉できません(原因はよく分かってないです)。
FileUtils::DryRun
にすり替えられているため、テストを走らせてもファイルのコピーは行われておらず、代わりにcopy Gemfile CopyGemfile\n
というメッセージがstderrに出力されます。出力には最後に改行が入るため、注意です。
参考
FileUtils
をFileUtils::DryRun
に差し替える方法はFakeFSの以下の実装を参考にしました。
https://github.com/fakefs/fakefs/blob/master/lib/fakefs/base.rb
FakeFSの方ではremove_const
とconst_set
を使っているようです。今回const_set
を使わず代入を用いたことに深い意味はありません。
濫用はできませんが、応用が効きそうな手法ですね。