FileNotFoundExceptionの強制
-
03-07-2019 - |
質問
私がカバーしようとしているIOExceptionキャッチを含むコードのテストを書いています。 try / catchは次のようになります。
try {
oos = new ObjectOutputStream(new FileOutputStream(cacheFileName));
} catch (IOException e) {
LOGGER.error("Bad news!", e);
} finally {
最も簡単な方法はFileOutputStreamにFileNotFoundExceptionをスローさせるように思えますが、おそらく私はこれをすべて間違った方法で行っています。
ヒントはありますか?
解決
コメントから:
はい、質問は 本当に"を作成する方法 両方のLinuxに存在しないファイル およびWindows?" Windowsでは、私は使用することができます 'new File(" X:/")'、X:はドライブ 存在しない手紙。 Linuxでは、 これは動作しません 有効なファイル名。
java.io.File.createTempFileを見てください。それを使用してファイルを作成してから削除します。
おそらく次のように渡します:
File tempFile;
tempFile = createTempFile(getClass().getName(),
Long.toString(System.currentTimeMillis());
tempFile.delete();
プラットフォーム固有の方法で一意の名前を付ける必要があります。これは、存在することを(ほとんど)恐れずに安全に使用できます。
他のヒント
cacheFileName
を無効な名前または存在しないことがわかっている名前に設定できます。
テストには2つの部分があります。それを実現することと、正しい結果が得られたことを測定することです。
フォールトインジェクション
最も簡単な答えは、すでに述べたものです。これは、 cacheFileName
を決して存在しないファイルに設定することです。これはおそらくこの状況で最も実用的な答えです。
ただし、 IOException
などの任意の条件を発生させるために、本当に必要なのはフォールインジェクション。これにより、ソースコードをインストルメントすることを強制せずに、コードにエラーが発生します。これを行うためのいくつかの方法を次に示します。
- モックオブジェクトファクトリメソッドを使用して、オーバーライドされた
ObjectOutputStream
またはFileOutputStream
を作成できます。テストコードでは、実装は必要に応じてIOException
をスローし、製品コードでは通常の動作を変更しません。 - 依存性注入モックオブジェクトを適切な場所に配置するには、春または縫い目を「インジェクト」する;作業を行っているクラスに適切なオブジェクト。これらのフレームワークは、注入されるオブジェクトに対しても優先順位を持っていることがわかります。そのため、単体テスト中に、テストオブジェクトでプロダクションオブジェクトをオーバーライドできます。
- アスペクト指向プログラミング 構造を変更する代わりにコードのすべてで、AOPを使用して適切な場所に障害を挿入できます。たとえば、 AspectJ を使用すると、例外をスローする場所、およびアドバイス目的の例外をスローします。
Javaのフォールトインジェクションには他にも答えがあります。たとえば、 AProbe という製品は、CでAOPと呼ばれるものを先駆けて開発しました。 Java製品があります。
検証
スローされた例外を取得することは良いスタートですが、正しい結果が得られたことを検証する必要もあります。そこにあるコードサンプルが正しいと仮定して、その例外をログに記録したことを検証する必要があります。上記の誰かが、ロガーにMockオブジェクトを使用することについて言及しましたが、これは実行可能なオプションです。ここでAOPを使用して、ロガーへの呼び出しをキャッチすることもできます。
ロガーは log4j であると想定しています。同様の問題を解決するために、log4j出力をキャプチャする独自のlog4jアペンダーを実装しました。具体的には ERROR
と FATAL
のみをキャプチャします。ケース。アペンダーは log4j.xml
で参照され、テスト実行中にアクティブ化されてエラーログ出力をキャプチャします。これは本質的にはモックオブジェクトですが、log4j Logger
を取得したすべてのコードを再構築する必要はありませんでした。
コードのテストを書いています IOExceptionキャッチが含まれている 私がカバーしようとしていること。
私はあなたの目標を完全に理解しているわけではありませんが、例外がスローされるかどうかをテストしたい場合は、例外をスローすることを期待するテストを伝えることができます:
@Test(expected=IOException.class)
例外がスローされない場合、テストは失敗し、スローされた場合は成功します( cacheFileName
ファイルが存在しない場合など)。
FileNotFoundExceptionは明らかにキャッチをトリガーします。 javadocには、スローされるケースが記載されています。
ObjectOutputStreamコンストラクターがIOExceptionをスローできることも考慮する必要があるため、テストでこのケースをカバーすることをお勧めします。
2つの簡単な方法は、cacheFileNameを存在しないファイルに設定するか、指定されたファイルを読み取り専用アクセスに設定することです。
-John
コードは現在作成されているので、LOGGERオブジェクトでerror()呼び出しをモックアウトし、IOExceptionが予想されるときに呼び出されるかどうかを確認できます。
テストしたいという願望が、記述されたコードの根本的な問題を明らかにしたかもしれません。エラーが発生していますが、ファイルへの書き込みが成功したかどうかを判断するコードの他のセクションを提供するブール値またはフラグ値(ファイル名を特別なパターンに設定)はありません。これが関数に含まれている場合は、ブール値を返すか、オブジェクトレベルの変数を設定できます。
cacheFileName = "thisFileShouldNeverExistAndIfItDoesYouAreScrewingUpMyTests";
プログラムを使用してファイル名が絶対に存在しないことを確認するための手順を実行し、フープを介してジャンプするか、99.99999%のケースでは決して存在しない文字列を使用できます。
これがあなたの意図したことだと思います。
if(new File(cachedFile).exists()) {
oos = new ObjectOutputStream(new FileOutputStream(cacheFileName));
//do your code here
} else {
throw new FileNotFoundException("File doesn't exist!");
}