Java Assertj + Mockito
Java Assertj + Mockito
Assertj
共通
- 同値: isEqualTo
assertThat("Foo").isEqualTo("Foo"); assertThat("Foo").isNotEqualTo("Bar");
- Null: isNull/isNotNull
assertThat(actual).isNull(); assertThat(actual).isNotNull();
- 同一インスタンス: isSameAs/isNotSameAs
assertThat(bar1).isSameAs(bar2); assertThat(bar1).isNotSameAs(bar2);
- インスタンスの型: isInstanceOf/isNotInstanceOf
assertThat(baz).isInstanceOf(Baz.class); assertThat(qux).isInstanceOf(Baz.class).isInstanceOf(Qux.class); assertThat(qux).isNotInstanceOf(Baz.class);
- toString値: hasToString
assertThat(fooBar).hasToString("FooBar"); // toString()の値確認
- 注釈: as
assertThat("Foo").as("AssertJ sample").isEqualTo("Bar");
文字列
- 先頭/末尾一致
assertThat("FooBar").startsWith("Foo"); assertThat("FooBar").endsWith("Bar");
- 大小無視の一致
assertThat("Foo").isEqualToIgnoringCase("FOO");
- 空文字/Null
assertThat("").isEmpty(); assertThat(actual).isNullOrEmpty(); // null
- 正規表現比較
assertThat("FooBarBaz").matches("F..B..B..").matches("F.*z");
- 数字かどうか
assertThat("1234567890").containsOnlyDigits();
- 行数確認
assertThat("foo\nbar\nbaz").hasLineCount(3); assertThat("foo\r\nbar\r\nbaz").hasLineCount(3);
数値
- 範囲(Between)
assertThat(7).isBetween(0, 9).isBetween(7, 7); assertThat(7).isCloseTo(5, within(2)); // 5 ± 2
- 大なり/小なり
assertThat(7).isGreaterThan(6).isGreaterThanOrEqualTo(7); assertThat(7).isLessThan(8).isLessThanOrEqualTo(7);
Collection(List/Set等)
- hasSize: サイズ確認
assertThat(actuals).hasSize(4);
- isEmpty: 空か
assertThat(actuals).isEmpty();
- contains: 並び順は検証しない。含まれていればOK
List<String> actuals = Lists.newArrayList("Lucy", "Debit", "Anna", "Jack"); assertThat(actuals).contains("Lucy", "Anna");
- containsOnly: 並び順は検証しない。全て含むならOK
List<String> actuals = Lists.newArrayList("Lucy", "Debit", "Anna", "Jack"); assertThat(actuals).containsOnly("Debit", " Lucy", "Jack", "Anna");
- containsSequence: 並び順を検証。件数確認しない
List<String> actuals = Lists.newArrayList("Lucy", "Debit", "Anna", "Jack"); assertThat(actuals).containsSequence("Lucy", "Debit");
- containsSubSequence: 並び順を検証。件数確認しない。抜け漏れOK
List<String> actuals = Lists.newArrayList("Lucy", "Debit", "Anna", "Jack"); assertThat(actuals).containsSubsequence("Lucy", "Anna") .containsSubsequence("Lucy", "Jack");
- containsOnlyOnce: 含む かつ 重複なしならOK
List<String> actuals = Lists.newArrayList("Lucy", "Debit", "Anna", "Lucy"); assertThat(actuals).containsOnlyOnce("Debit", "Anna");
- containsAnyOf: いずれか1つがある
assertThat(actuals).containsAny("Debit", "Anna");
- extracting
// 特定フィールドのみ抽出 assertThat(list).extracting("name").containsExactly("佐藤","田中","鈴木");
Map
- containsEntry
assertThat(actuals).containsEntry("Key1", 101) .containsEntry("Key2", 202) .doesNotContainEntry("Key9", 999);
- containsKey
assertThat(actuals).containsKeys("Key2", "Key3") .doesNotContainKey("Key9");
- containsValue
assertThat(actuals).containsValues(202, 303) .doesNotContainValue(999);
- hasSize/isEmpty もある
Iterable関係
まとめて検証
- allSatisfy: 全て満たす
assertThat(hobbits).allSatisfy(character -> {
assertThat(character.getRace()).isEqualTo(HOBBIT);
assertThat(character.getName()).isNotEqualTo("Sauron");
});
- anySatisfy: いずれかを満たす
assertThat(hobbits).anySatisfy(character -> {
assertThat(character.getRace()).isEqualTo(HOBBIT);
assertThat(character.getName()).isEqualTo("Sam");
});
- noneSatisfy: 全て満たさない
assertThat(hobbits).noneSatisfy(character -> assertThat(character.getRace()).isEqualTo(ELF));
特定の1つを検証
- first/element/last: 最初/間/最後
Iterable<TolkienCharacter> hobbits = list(frodo, sam, pippin);
assertThat(hobbits).first().isEqualTo(frodo);
assertThat(hobbits).element(1).isEqualTo(sam);
assertThat(hobbits).last().isEqualTo(pippin);
単一要素
assertThat(babySimpsons).singleElement()
.isEqualTo("Maggie");
特定フィールドの抽出
assertThat(users).extracting((u) -> tuple(u.id, u.rank)) .contains(tuple("abc", 10)) .contains(tuple("def", 20)); assertThat(users).extracting("id", "rank") .contains(tuple("abc", 10)) .contains(tuple("def", 20));
assertThat(params) .extracting(Param::key, Param::value) .containsExactlyInAnyOrder( tuple("analysisId", "abc"), tuple("projectId", "cde"));
assertAll (全て実行する)
失敗するものがあっても assertAll 内は全て検証される(ただし、結果が少々見にくい)
assertThat(persons.get(0)) .satisfies(p -> assertAll( () -> assertThat(p.getName()).isEqualTo("SYM"), () -> assertThat(p.getAge()).isEqualTo(0), () -> assertThat(p.getJob()).isEqualTo("Engineer") ));
例外
- 例外確認
assertThatThrownBy(() -> { throw new Exception("boom!"); }) .isInstanceOf(Exception.class) // 継承クラス含む .isExactlyInstanceOf(IOException.class) // 一致 .hasMessageContaining("boom");
- 例外が発生しない
// どちらも同じ assertThatNoException().isThrowBy(() -> System.out.println("")); assertThatCode(() -> System.out.println("OK")).doesNotThrowAnyException();
- 指定した例外発生確認
assertThatExceptionOfType(IOException.class) .isThrownBy(() -> { throw new IOException("boom!"); }) .withMessage("%s!", "boom") .withMessageContaining("boom") .withNoCause();
- 特定の例外確認
- assertThatNullPointerException
- assertThatIllegalArgumentException
- assertThatIllegalStateException
- assertThatIOException
assertThatIOException().isThrownBy(() -> { throw new IOException("boom!"); }) .withMessage("%s!", "boom") .withMessageContaining("boom") .withNoCause();
カスタムAssertion
var fooObj = new FooClass(); // 略 assertThat(fooObj).hasValue("bar"); public class FooClassAssert extends AbstractAssert<FooClassAssert, FooClass> { public FooClassAssert(FooClass actual) { // 定型文 super(actual, FooClassAssert.class); } public static FooClassAssert assertThat(FooClass actual) { // 定型文 return new FooClassAssert(actual); } public FooClassAssert hasValue(String key) { // 独自Assertion isNotNull(); if (actual.getValue(key) == null) { failWithMessage("エラーメッセージ"); } return this; // メソッドチェーンのために必須 } }
Mockito
- mock 全体をモック化
var mockedService = new Mock(MessageService.class); // モック when(mockedService).getMessage(any()).thenReturn("モック化"); doReturn("モック化").when(mockedService).getMessage(any()); // 呼び出し回数検証 verify(mockedService, times(2)).getMessage(any());
- spy 一部のみをモック化
var mockedService = new Spy(MessageService.class); doReturn("モック化").when(mockedService).getMessage(any());
※テスト対象クラスをspyするのは避けた方が良い。責務が大きくなり図来ている兆候 (シングルトンクラスのメソッドのテスト無理やりできるが非推奨。場合による)
- その他
mockito でコンストラクターの mock を使ったテストをしたい (Mockito 3.5.0 以降)
ref
以下も参考になりそう