Scalaとは全然関係ない話です。
あとで書き直します。
Scalaの案件に携わり、関数型言語とは......みたいなものを学ぼうとしていたら離プロして結局果たせずじまい。
その後、別案件でテストカバレッジチームに配属されました。
既存のプロダクトコードにJUnitでテストを書いていく、それだけです。
そして依存関係が少なく、独立したメソッドなら Mockito
さまさまで楽にかけます。
しかし困るのが、パラメーターやパラメーターに使われるオブジェクトの一部が違うパターン。
もちろんJUnit5などでは @Parameterizedtest
などの便利な機能が用意されてはいますが、それだけで充当できるわけでもなく。
もちろん共通部分をメソッドに切り出す、という手段を使いつつも、やはりどうにも同じメソッドを呼び出している感が拭えないし、柔軟性がないような気がする。
そしてもう一点。
たとえば @BeforeEach/@BeforeAll
や @AfterEach/@AfterAll
に含めたくないけど、シングルトンやstaticなフィールドにモックを突っ込みたいとき。
既存テストに影響を与えず、という形です。
もちろん各テストメソッド内で、設定する/解除する、というのを組み込めばいいのですが、しょせん人間、間違いはあります。最悪の場合、モックが設定されたまま使い回される可能性もあり、テスト品質に影響がでます。
そんなこんなで思い当たったのが、Scalaをやっていたときに学んだローンパターンや関数型インターフェースの組み合わせ。
private void withMock(Consumer<MotoniModoshitaiResource> c) {
MotoniModoshitaiResource mock = Mockito.mock(MotonimodoshitaiResource.class);
MotoniModoshitaiResource moto = Taisho.mmr;
reflectionTokadeMuriyariSet(mock);
c.accept(mock);
reflectionTokadeMuriyariSet(moto);
}
@Test
void testHoge() {
withMock(c -> {
// テストコード書く
// ここのcはモックなのでverifyとかも可能
});
}
これなら使っている側は、静的クラスや外部リソースの復元を気にすることなく、メソッド呼び出し内でテストを記述するだけでことたります。
また上記のような考え方をすることで、微妙に異なるフィールド値を使うテストも差分だけを書けばよくなるような気がします。
パラメーターが NanrakanoObj
の各フィールドの値の違いによるテストを書きたければ
Consumer<NanrakanoObj>
を引数に持つメインテストケースを共用すればいいのです。
private Result testFieldDakeChigau(Consumer<Target> c) {
Target t = new Target();
t.setName("..."); // 共通的な設定
/* 共通的な処理 */
c.accept(t); // ここで各パターンで違うことをする
Result r = xxx.exec(t);
assertEquals(r.name(), "..."); // 共通的なテスト
return r;
}
@Test
void test1() {
Result r = testFieldDakeChigau(c -> c.setStatus("x"));
assertEquals("X", r.getStatus());
}
@test
void test2() {
Result r = testFieldDakeChigau(c -> c.setType("b"));
assertEquals("B", r.getType());
}