技術開発日記

技術やら日々思ったことを綴ってます。

throwsするべきかtry/catchするべきか

JUnitで例外が発生する場合のテストを書くとき、throwsするべきかtry/catchするべきかを
悩んでいる場合、特別な理由が無い限りはthrowsにするべきという指摘を頂いた。

じゃ、なんでtry/catchではなくthrowsのがいいか。

1.コードが綺麗になる。
2.エラー出力の内容がより詳細

まず1。
以下のコードを見ると確かにthrowsしている方が簡潔で綺麗。

try/catch

    @Test
    public void testSample1() {
        try {
            target.check();
        } catch (Exception e) {
            fail();
        }
    }

throws

    @Test
    public void testSample1() throws Exception{
        target.check();
    }


そして、次に2。
これも実施してみればわかるけど、try/catchの場合は

java.lang.AssertionError:
at org.junit.Assert.fail(Assert.java:91)
at org.junit.Assert.fail(Assert.java:98)

といったように、何が原因でエラーになったかがわかない。
これはデバッグ作業を行う際に結構手間になってしまう。

その半面、throwsにした場合
以下のように例外の内容を出力してくれるため、何が原因で失敗したのかがすぐに判断できる。
※例外にメッセージなどを詰めている場合

jp.co.sample.DaoException: 登録に失敗しました。
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
Caused by: java.lang.IllegalArgumentException
at jp.co.sample.SampleDaoImpl.regist(SampleDaoImpl.java:100)
... 25 more


といったように上記の理由からも、もしtry/catchかthrowsで迷っている場合はthrowsの方で実装した方がいいかもしれない。

ちなみにthrowsにする場合は各例外をthrowするのでなく、全てExceptionにしてthrowした方がいいという指摘も頂いた。
というのも、もし各例外をthrowするとき
例外が多い場合はその各例外を記述しないといけなくなるというのと、
テストする対象が違う例外をthrowするようになったとき、対象のテストクラスも例外を追加しないといけなくなる。
なので、ここはまとめてExceptionとしてthrowする。

ただ、これは個人的にはちょっと気持ち悪いといえば気持ち悪い。
テスト対象を変更したのに、テストに変更がないってなんとなくバグの温床になる気がしてならない。
これに関しては、メリット・デメリットがあると思うので、そこを見極めての実装になるかなと思う。