Groovyでクロージャを使って例外のテストを局所的にしてみる
id:taediumさんのエントリの
あと気に入ったのは例外のテスト。期待する例外をテストメソッドの属性に書くと、例外をスローするかもしれないスコープが広くなりすぎてしまうですが、デリゲートを使うことでとても局所的にできます。例外を戻してさらにテストすることもできます。
という日本語部分だけみて脊髄反射で書いてみた。
元々のxUnit.netのコードは全然みてないので(デリゲートわからない><)、全く関係ない話かもしれないけど気にしない気にしない。
import junit.framework.AssertionFailedError class SampleTest extends GroovyTestCase { // enhancing GroovyTestCase static { GroovyTestCase.metaClass.assertThrown = { Class throwable, Closure closure -> try { closure.call() } catch (e) { if (!throwable.isInstance(e)) { throw new AssertionFailedError("unexpected exception is thrown. expected: ${throwable}, but: ${e.class}") } return e } throw new AssertionFailedError("expected exception was not thrown. expected: ${throwable}") } } // →Green void testExpectedException() { assertThrown(RuntimeException) { throw new RuntimeException("HOGEHOGE") } } // →Green void testExpectedException_usingReturnValue() { def e = assertThrown(RuntimeException) { throw new RuntimeException("HOGEHOGE") } assert e.message == "HOGEHOGE" } // →Red: unexpected exception is thrown. expected: class java.lang.RuntimeException, but: class java.io.IOException void testUnexpectedException() { assertThrown(RuntimeException) { throw new IOException("HOGEHOGE") } } // →Red: expected exception was not thrown. expected: class java.lang.RuntimeException void testNoException() { assertThrown(RuntimeException) { // do nothing } } }
try-catchや@Test(expected)よりも良いかもしれぬ。
と、こんなの普通に思いつくことだから、もしかしてすでにある?と思って調べてみたら、あったよママン。
- http://groovy.codehaus.org/api/groovy/util/GroovyTestCase.html
- String shouldFail(Class clazz, Closure code)
- String shouldFail(Closure code)
- String shouldFailWithCause(Class clazz, Closure code)
↓こんな風に使える。
class SampleTest extends GroovyTestCase { void testExpectedException() { shouldFail(RuntimeException) { throw new RuntimeException("HOGEHOGE") } } void testExpectedException_usingReturnValue() { def exceptionMessage = shouldFail(RuntimeException) { throw new RuntimeException("HOGEHOGE") } assert exceptionMessage == "HOGEHOGE" } void testUnexpectedException() { shouldFail(RuntimeException) { throw new IOException("HOGEHOGE") } } void testNoException() { shouldFail(RuntimeException) { // do nothing } } }
知らなかった。こんどから使おうっと。