どんなものにも例外はある…。そうこの命題にも。
冗談はさておき、本題です。だっちダッチさまが
例外処理のテストは厄介という
興味深い話をされております。
しかし、ちょっと不思議に思ったところがあったので突っ込ませてもらいましょう。
件のサンプルコードは
Dim sw As StreamWriter
Try
' ファイルに書き込む処理
Catch ex As IOException
' IOException 時の対策
Finally
sw.Close()
End Try
といったもので、任意の場所で例外をthrowするツールを利用してテストを行うとした場合、
Finally部分のClose()で例外がthrowされるケースをもらすのではないかという話でした。
件のサンプルコードはJavaで書くと以下のようになります。
byte[] buffer;
OutputStream out;
try {
out.write(buffer);
} catch (IOException e) {
// IOException時の処理
} finally {
try {
// ストリームの後始末
out.close();
} catch (IOException e) {
// 外のtry-catchのExceptionを生かすためにここでは敢えて握りつぶす
}
}
finallyでclose()をするわけですが、close()メソッドがまたIOExceptionをthrowするため、try-catchが2重になります。
IOExceptionはチェック例外のため、try-catchで処理するか、
このコードが書かれているメソッドがさらに上にthrowするようにメソッドの宣言を記述するかしなくてはなりません。
Javaで一番使われているであろうIDEのEclipseには任意の場所で例外を発生させることが出来ます。
しかし、件のコードでfinallyのclose()時に例外が発生するケースは当然ながら入れ子のtry-catchとなっているため、
テストを漏らす事は考えにくいのです。
私の手元の環境には.NETの開発環境は入っていないのですが、VBはclose()で未チェック例外をthrowするのでしょうか?
問題外のケース
そもそもきっちりと正しい例外処理がされていない状況では、任意の場所で例外をthrowし、カバレッジを通そうとも潜在的にバグが残ります。
public void hoge() throws IOException {
byte[] buffer;
OutputStream out;
try {
out.write(buffer);
} finally {
// ここで例外が発生すると本来の例外に成り代わって
// close()時の例外がthrowされてしまう
out.close();
}
}
このあたりはtry-catchの落とし穴の部分であることは確かです。
きっちり例外処理を書くとかなりブロックの入れ子が深くなりますし、行数も多い。
しかも、普段は問題なく動くのだから適当な例外処理コードが書かれていても気づかないことが多いでしょう。
件のソースでカバレッジが通っていてもバグが検出できないのではないか?という疑問は
そもそも例外処理が正しく行われているか?という問題に帰着するのではないでしょうか。
そして、そういった危ういコードはFindbugsなどのバグパターン検出ツールでサーチ&デストロイというのが
正しい対処ではないでしょうか。
投稿日時 : 2007年8月5日 22:39