- JAVA
AssertJの使い方|assertThatの早見表(文字列・リスト・例外・日付)
AssertJ は、assertThat(実際の値).検証メソッド(期待値) の形で、テストの判定を「文章のように」つなげて書けるライブラリです。 値の型に合わせて使えるメソッドが変わるので、IDE の補完で候補が出ます。
import static org.assertj.core.api.Assertions.*;
assertThat(user.getName()).isEqualTo("Taro");
assertThat(list).hasSize(3).contains("b").doesNotContain("z");
assertThatThrownBy(() -> service.find(-1))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("id");
失敗したときのメッセージが詳しいのも特徴です。 同じ失敗を JUnit と AssertJ で比べると、次のようになりました。
| 判定 | JUnit Jupiter の失敗メッセージ | AssertJ の失敗メッセージ |
|---|---|---|
リストに "c" がある |
expected: <true> but was: <false> |
Expecting List12: ["a", "b"] to contain: ["c"] but could not find the following element(s): ["c"] |
| 順番どおりか | expected: <[a, b, c]> but was: <[b, a, c]> |
何番目の要素が違うかを1行ずつ表示 |
| 例外の型 | Unexpected exception type thrown, expected: <…IllegalStateException> but was: <…NumberFormatException> |
期待した型と、実際の例外のメッセージとスタックトレース |
確認環境:AssertJ 3.27.7(GitHub のタグで最新の安定版。Spring Boot 4.1.1 が管理する版と同じ)を、タグ assertj-build-3.27.7 のソースからビルドし、OpenJDK 21.0.10(Linux)で動かしました。この記事の早見表のコードは 96 個の判定がすべて通ること、「迷いやすい3つの違い」の表は16通りを実行した結果であること、失敗メッセージは実際の出力であることを確かめています。JUnit 側のメッセージは JUnit Jupiter 5.10.1、SoftAssertionsExtension は JUnit Platform Console 1.9.1 で実行した結果です(確認日 2026年10月13日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「AssertJの使い方|assertThatの早見表(文字列・リスト・例外・日付)」
依存の追加
Spring Boot のプロジェクトなら、spring-boot-starter-test に AssertJ が入っています(Boot 4.1.1 が管理する版は 3.27.7)。単体で入れる場合は次のとおりです。
// build.gradle.kts
dependencies {
testImplementation("org.assertj:assertj-core:3.27.7")
}
<!-- pom.xml -->
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.27.7</version>
<scope>test</scope>
</dependency>
AssertJ 3.x は Java 8 以上で動きます(ビルド設定の java.version が 8)。4.0.0 はマイルストーン版(4.0.0-M1)が出ている段階です。
import static org.assertj.core.api.Assertions.*; を1行書くと、assertThat などが全部使えます。 JUnit の Assertions と名前がぶつかるので、同じファイルで両方を * で読み込まないようにします。BDD(振る舞い駆動)の書き方が好みなら、BDDAssertions.then(…) も同じ機能です。JUnit そのものの書き方は、関連記事「JUnitの使い方|単体テストの書き方と観点【JUnit 5・6】」で扱っています。
JUnit の assert と AssertJ の対応表
| JUnit(Assertions) | AssertJ |
|---|---|
assertEquals(expected, actual) |
assertThat(actual).isEqualTo(expected) |
assertNotEquals(a, b) |
assertThat(b).isNotEqualTo(a) |
assertTrue(cond) |
assertThat(cond).isTrue()(できれば型別のメソッドで書く) |
assertFalse(cond) |
assertThat(cond).isFalse() |
assertNull(x)・assertNotNull(x) |
assertThat(x).isNull()・isNotNull() |
assertSame(a, b) |
assertThat(b).isSameAs(a) |
assertEquals(0.3, x, 1e-9) |
assertThat(x).isCloseTo(0.3, within(1e-9)) |
assertArrayEquals(a, b) |
assertThat(b).containsExactly(a) |
assertIterableEquals(a, b) |
assertThat(b).containsExactlyElementsOf(a) |
assertTrue(list.contains("c")) |
assertThat(list).contains("c") |
assertEquals(3, list.size()) |
assertThat(list).hasSize(3) |
assertThrows(X.class, () -> …) |
assertThatThrownBy(() -> …).isInstanceOf(X.class) |
assertDoesNotThrow(() -> …) |
assertThatCode(() -> …).doesNotThrowAnyException() |
assertAll(() -> …, () -> …) |
SoftAssertions.assertSoftly(softly -> { … }) |
assertEquals(e, a, "メッセージ") |
assertThat(a).as("説明").isEqualTo(e) |
fail("…") |
fail("…")(AssertJ にもある) |
引数の順番が逆なのが一番の違いです。 JUnit は assertEquals(期待値, 実際の値)、AssertJ は assertThat(実際の値).isEqualTo(期待値) です。JUnit で順番を取り違えると、メッセージの expected と but was が逆に出ます。
型別メソッド早見表
すべての型で使える
| メソッド | 例 | 意味 |
|---|---|---|
isEqualTo・isNotEqualTo |
assertThat("abc").isEqualTo("abc") |
equals で比べる |
isNull・isNotNull |
assertThat(x).isNotNull() |
null かどうか |
isSameAs・isNotSameAs |
assertThat(s).isNotSameAs("a") |
同じインスタンスか(==) |
isInstanceOf |
assertThat(x).isInstanceOf(String.class) |
型 |
isIn・isNotIn |
assertThat("b").isIn("a", "b", "c") |
候補のどれかか |
satisfies |
assertThat(x).satisfies(v -> assertThat(v).hasSize(1)) |
中で別の判定をする |
matches |
assertThat("abc").matches(s -> s.length() == 3, "3文字") |
条件式で判定 |
as |
assertThat(age).as("年齢").isGreaterThan(17) |
失敗時に [年齢] を前に付ける |
withFailMessage |
.withFailMessage("18歳以上のはず: %d", age) |
失敗メッセージを置き換える |
as と withFailMessage は、判定メソッドより前に書きます。 後ろに書くと、判定が先に失敗して効きません。
文字列(String)
| メソッド | 例 | 意味 |
|---|---|---|
startsWith・endsWith |
assertThat("Hello World").startsWith("Hello") |
前方・後方一致 |
contains・doesNotContain |
.contains("lo W") |
部分一致 |
containsIgnoringCase |
assertThat("Hello").containsIgnoringCase("ELL") |
大文字小文字を無視して部分一致 |
isEqualToIgnoringCase |
.isEqualToIgnoringCase("hello") |
大文字小文字を無視して一致 |
isEqualToIgnoringWhitespace |
assertThat("a b").isEqualToIgnoringWhitespace("ab") |
空白を無視して一致 |
isEqualToNormalizingNewlines |
assertThat("a\r\nb").isEqualToNormalizingNewlines("a\nb") |
改行コードの違いを無視 |
isEmpty・isNotEmpty |
assertThat("").isEmpty() |
空文字か |
isBlank・isNotBlank |
assertThat(" ").isBlank() |
空白だけか |
isNullOrEmpty |
assertThat((String) null).isNullOrEmpty() |
null か空文字か |
hasSize |
assertThat("abc").hasSize(3) |
文字数 |
matches |
.matches("\\d{4}-\\d{2}-\\d{2}") |
正規表現に全体が一致 |
containsOnlyDigits |
assertThat("12345").containsOnlyDigits() |
数字だけ |
containsOnlyOnce |
assertThat("banana").containsOnlyOnce("b") |
1回だけ出てくる |
containsSequence |
assertThat("banana").containsSequence("an", "an") |
この順に続けて出てくる |
数値
| メソッド | 例 | 意味 |
|---|---|---|
isGreaterThan・isLessThan |
assertThat(10).isGreaterThan(5) |
より大きい・小さい |
isGreaterThanOrEqualTo・isLessThanOrEqualTo |
.isLessThanOrEqualTo(10) |
以上・以下 |
isBetween |
assertThat(10).isBetween(1, 10) |
範囲内(両端を含む) |
isPositive・isNegative・isZero |
assertThat(0).isZero() |
正・負・0 |
isEven・isOdd |
assertThat(4).isEven() |
偶数・奇数 |
isCloseTo(…, within(…)) |
assertThat(0.1 + 0.2).isCloseTo(0.3, within(1e-9)) |
誤差の範囲内(offset も同じ) |
isCloseTo(…, withinPercentage(…)) |
assertThat(103).isCloseTo(100, withinPercentage(5)) |
%の範囲内 |
isEqualByComparingTo |
assertThat(new BigDecimal("1.0")).isEqualByComparingTo("1.00") |
compareTo で比べる |
assertThat(0.1 + 0.2).isEqualTo(0.3) は失敗しました(but was: 0.30000000000000004)。小数は isCloseTo で比べます。BigDecimal の isEqualTo は 1.0 と 1.00 を別の値とみなすので、値だけ比べるなら isEqualByComparingTo を使います。理由は、関連記事「Java BigDecimalの使い方|金額計算の丸めと比較の注意点」で扱っています。
List・配列(Iterable)
| メソッド | 例(list は ["a", "b", "c"]) |
意味 |
|---|---|---|
hasSize・isEmpty・isNotEmpty |
assertThat(list).hasSize(3) |
件数 |
contains |
.contains("b") |
含む(順番・他の要素は問わない) |
doesNotContain |
.doesNotContain("z") |
含まない |
containsExactly |
.containsExactly("a", "b", "c") |
全部・この順番で |
containsExactlyInAnyOrder |
.containsExactlyInAnyOrder("c", "a", "b") |
全部・順番は問わない(重複の数も合わせる) |
containsOnly |
.containsOnly("c", "b", "a") |
これ以外を含まない(重複は気にしない) |
containsSequence |
.containsSequence("b", "c") |
この並びが続けてある |
containsAnyOf |
.containsAnyOf("x", "a") |
どれか1つ以上 |
hasSameElementsAs |
.hasSameElementsAs(Set.of("c", "b", "a")) |
別のコレクションと同じ要素 |
doesNotHaveDuplicates |
.doesNotHaveDuplicates() |
重複なし |
isSorted |
.isSorted() |
昇順に並んでいる |
first・last・element(i) |
.element(1).isEqualTo("b") |
その要素で続けて判定 |
singleElement |
assertThat(List.of("x")).singleElement().isEqualTo("x") |
1件だけで、その中身 |
allMatch・anyMatch・noneMatch |
.allMatch(s -> s.length() == 1) |
条件 |
allSatisfy |
.allSatisfy(s -> assertThat(s).hasSize(1)) |
全要素に判定 |
filteredOn |
.filteredOn(s -> s.compareTo("a") > 0).containsExactly("b", "c") |
絞り込んでから判定 |
| 配列 | assertThat(new int[]{1, 2, 3}).containsExactly(1, 2, 3) |
配列も同じメソッド |
迷いやすい3つの違い
期待 ("a", "b") に対して |
containsExactly |
containsExactlyInAnyOrder |
containsOnly |
contains |
|---|---|---|---|---|
実際 ["a", "b"] |
成功 | 成功 | 成功 | 成功 |
実際 ["b", "a"] |
失敗(順番) | 成功 | 成功 | 成功 |
実際 ["a", "b", "b"] |
失敗 | 失敗(数) | 成功 | 成功 |
実際 ["a", "b", "x"] |
失敗 | 失敗 | 失敗(余分) | 成功 |
Map
| メソッド | 例(map は {a=1, b=2}) |
意味 |
|---|---|---|
containsKey・doesNotContainKey |
assertThat(map).containsKey("a") |
キー |
containsKeys・containsValues |
.containsKeys("a", "b").containsValues(1, 2) |
複数のキー・値 |
containsEntry |
.containsEntry("b", 2) |
キーと値の組 |
containsOnlyKeys |
.containsOnlyKeys("b", "a") |
キーはこれだけ |
extractingByKey |
.extractingByKey("a").isEqualTo(1) |
その値で続けて判定 |
hasSize |
.hasSize(2) |
件数 |
Optional
| メソッド | 例 | 意味 |
|---|---|---|
isPresent・isEmpty |
assertThat(Optional.empty()).isEmpty() |
値があるか |
contains・hasValue |
assertThat(Optional.of("x")).contains("x") |
中身が等しい |
get() |
assertThat(Optional.of(5)).get().isEqualTo(5) |
中身で続けて判定 |
Optional そのものの使い方は、関連記事「Java Optionalの使い方|orElseとorElseGetの違いと使う場所」で扱っています。
日付・時刻(java.time)
| メソッド | 例(d は 2026-10-13) |
意味 |
|---|---|---|
isBefore・isAfter |
assertThat(d).isBefore(LocalDate.of(2026, 12, 31)) |
より前・後(同じ日は含まない) |
isBeforeOrEqualTo・isAfterOrEqualTo |
assertThat(t).isAfterOrEqualTo("2026-10-13T09:30:15") |
以前・以後 |
isBetween |
assertThat(d).isBetween("2026-10-01", "2026-10-31") |
範囲内(両端を含む) |
hasYear・hasMonth・hasDayOfMonth |
.hasYear(2026).hasMonth(Month.OCTOBER).hasDayOfMonth(13) |
年・月・日 |
| 文字列で比べる | assertThat(d).isEqualTo("2026-10-13") |
ISO 形式の文字列を日付として解釈 |
isCloseTo(…, within(n, 単位)) |
assertThat(t).isCloseTo(t2, within(2, ChronoUnit.SECONDS)) |
n 秒以内などのずれを許す |
isEqualToIgnoringSeconds |
.isEqualToIgnoringSeconds(LocalDateTime.of(2026, 10, 13, 9, 30, 59)) |
秒以下を無視 |
isToday |
assertThat(LocalDate.now()).isToday() |
今日か |
現在時刻を使う処理は、isCloseTo(…, within(…)) で「数秒のずれ」を許すと安定します。 日付の書式は、関連記事「Java DateTimeFormatterパターン一覧|日付と文字列の変換」で扱っています。
例外の判定
assertThatThrownBy(一番よく使う形)
assertThatThrownBy(() -> userService.register(new UserRequest("", -1)))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("age must be >= 0") // 完全一致
.hasMessageContaining(">= 0") // 部分一致
.hasMessageStartingWith("age")
.hasNoCause();
書き方の一覧
| 書き方 | 向いている場面 |
|---|---|
assertThatThrownBy(() -> …).isInstanceOf(X.class) |
型とメッセージを続けて確かめる |
assertThatExceptionOfType(X.class).isThrownBy(() -> …).withMessageContaining("…") |
型を先に書いて読みやすくする |
assertThatIllegalArgumentException().isThrownBy(() -> …) |
よく使う型の専用版(NullPointerException・IllegalStateException・IOException などもある) |
assertThatCode(() -> …).doesNotThrowAnyException() |
例外が出ないこと |
Throwable t = catchThrowable(() -> …); |
例外を取り出して、後でまとめて判定 |
X e = catchThrowableOfType(X.class, () -> …); |
型を指定して取り出し、独自のフィールドを見る |
原因(cause)の判定は次のとおりです。
assertThatThrownBy(() -> repository.save(user))
.isInstanceOf(IllegalStateException.class)
.hasCauseInstanceOf(IOException.class) // 直接の原因
.hasRootCauseMessage("disk"); // 一番奥の原因のメッセージ
例外が出なかったときは、次のメッセージで失敗しました。
Expecting code to raise a throwable.
例外の種類と使い分けは、関連記事「Java 例外一覧|種類・原因・対処の早見表と使い分け」で扱っています。
extracting と tuple:オブジェクトのリストを判定する
オブジェクトのリストから、特定のフィールドだけを取り出して判定するのが extracting です。
List<Item> items = List.of(new Item("pen", 100), new Item("note", 250));
// 1つのフィールド
assertThat(items).extracting(Item::getName).containsExactly("pen", "note");
assertThat(items).extracting("name").containsExactly("pen", "note"); // 名前でも書ける
// 複数のフィールドは tuple で
assertThat(items)
.extracting(Item::getName, Item::getPrice)
.containsExactly(tuple("pen", 100), tuple("note", 250));
// 絞り込んでから取り出す
assertThat(items).filteredOn("price", 100).extracting("name").containsExactly("pen");
// リストのフィールドを平らにする
assertThat(items).flatExtracting(Item::getTags).containsExactly("office", "office", "paper");
| 書き方 | 長所 | 短所 |
|---|---|---|
extracting(Item::getName) |
名前を変えるとコンパイルエラーで気づく | getter かメソッドが要る |
extracting("name") |
getter が無いフィールドも取れる | 名前の打ち間違いは実行するまで分からない |
usingRecursiveComparison:中身で比べる
equals を実装していないクラスや、一部のフィールドを無視して比べたいときは、usingRecursiveComparison() を使います。 入れ子のオブジェクトの中までフィールドごとに比べます。
record Address(String city, String zip) {}
record User(String name, int age, Address address) {}
record UserDto(String name, int age) {}
User actual = new User("Taro", 20, new Address("Tokyo", "100-0001"));
// 中身が同じなら成功
assertThat(actual).usingRecursiveComparison()
.isEqualTo(new User("Taro", 20, new Address("Tokyo", "100-0001")));
// 一部のフィールドを無視(入れ子は「.」でつなぐ)
assertThat(actual).usingRecursiveComparison()
.ignoringFields("age", "address.zip")
.isEqualTo(new User("Taro", 99, new Address("Tokyo", "999")));
// 違う型(DTO)とも、同じ名前のフィールドで比べられる
assertThat(actual).usingRecursiveComparison()
.ignoringFields("address")
.isEqualTo(new UserDto("Taro", 20));
// 期待値で null のフィールドは比べない
assertThat(actual).usingRecursiveComparison()
.ignoringExpectedNullFields()
.isEqualTo(new User("Taro", 20, null));
// リストの要素ごとに中身で比べる
assertThat(List.of(actual))
.usingRecursiveFieldByFieldElementComparatorIgnoringFields("age")
.containsExactly(new User("Taro", 0, new Address("Tokyo", "100-0001")));
| オプション | 意味 |
|---|---|
ignoringFields("a", "b.c") |
指定したフィールドを比べない |
comparingOnlyFields("name") |
指定したフィールドだけ比べる |
ignoringExpectedNullFields() |
期待値の null のフィールドは比べない |
ignoringActualNullFields() |
実際の値の null のフィールドは比べない |
ignoringCollectionOrder() |
リストの順番を無視する |
withEqualsForType(…, X.class) |
型ごとに比べ方を決める |
withStrictTypeChecking() |
型も一致させる(既定は型が違っても比べる) |
ID や作成日時のように、テストのたびに変わる値を ignoringFields で外すと、DB から取り出したエンティティの判定が書きやすくなります。record の equals のしくみは、関連記事「Java recordの使い方|classとの違いと実行結果で学ぶ」で扱っています。
SoftAssertions:全部の失敗をまとめて出す
ふつうの assertThat は、最初の失敗でテストが止まります。 SoftAssertions は失敗を貯めておき、最後にまとめて報告します。画面の項目チェックのように、1回で全部の違いを知りたいときに使います。
JUnit 5 の拡張で使う(おすすめの形)
import static org.assertj.core.api.Assertions.*;
import org.assertj.core.api.SoftAssertions;
import org.assertj.core.api.junit.jupiter.InjectSoftAssertions;
import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(SoftAssertionsExtension.class)
class UserTest {
@InjectSoftAssertions
SoftAssertions softly;
record User(String name, int age, String email) {}
@Test
void softAssertions() {
User user = new User("Taro", 17, "taro@example");
softly.assertThat(user.name()).isEqualTo("Taro");
softly.assertThat(user.age()).as("age").isGreaterThanOrEqualTo(18);
softly.assertThat(user.email()).as("email").endsWith(".com");
// assertAll() は拡張がテストの最後に呼ぶ
}
}
実行結果です。2つの失敗が両方とも、行番号つきで出ました。
org.assertj.core.error.AssertJMultipleFailuresError:
Multiple Failures (2 failures)
-- failure 1 --
[age]
Expecting actual:
17
to be greater than or equal to:
18
at UserTest.softAssertions(UserTest.java:22)
-- failure 2 --
[email]
Expecting actual:
"taro@example"
to end with:
".com"
at UserTest.softAssertions(UserTest.java:23)
拡張を使わない書き方
// ラムダの中をまとめて判定
SoftAssertions.assertSoftly(softly -> {
softly.assertThat(user.name()).isEqualTo("Taro");
softly.assertThat(user.age()).isGreaterThan(17);
});
// 自分で assertAll() を呼ぶ
SoftAssertions softly = new SoftAssertions();
softly.assertThat(list).hasSize(3);
softly.assertAll(); // ← 忘れると、失敗しても何も起きない
new SoftAssertions() で作った場合、assertAll() を呼び忘れると、失敗が報告されずにテストが通ります。 拡張か assertSoftly を使うと、この呼び忘れが起きません。
失敗メッセージの読み方
AssertJ 3.27.7 で、わざと失敗させたときの出力です。
基本の形:Expecting actual … to …
Expecting actual:
"order-123"
to start with:
"ord_"
「actual(実際の値)が、to 以下(期待)を満たさなかった」と読みます。 isEqualTo だけは JUnit と同じ形になりました。
expected: "Hello Assertj"
but was: "Hello AssertJ"
expected が期待値、but was が実際の値です。文字列は " で囲まれるので、前後の空白の違いにも気づけます。
as() を付けると先頭に [説明] が付く
[年齢チェック]
Expecting actual:
17
to be greater than or equal to:
18
リストは「どこが違うか」まで出る
Expecting actual:
["b", "a", "c"]
to contain exactly (and in same order):
["a", "b", "c"]
but there were differences at these indexes:
- element at index 0: expected "a" but was "b"
- element at index 1: expected "b" but was "a"
[Extracted: name, price]
Expecting actual:
[("pen", 100), ("note", 250)]
to contain exactly (and in same order):
[("pen", 100), ("note", 200)]
but some elements were not found:
[("note", 200)]
and others were not expected:
[("note", 250)]
extracting を使うと、何を取り出したかが [Extracted: …] で先頭に付きます。not found は期待にあって実際に無いもの、not expected は実際にあって期待に無いものです。
再帰比較は、違うフィールドを全部並べる
Expecting actual:
User[name=Taro, age=20, address=Address[city=Tokyo, zip=100-0001]]
to be equal to:
User[name=Taro, age=21, address=Address[city=Osaka, zip=100-0001]]
when recursively comparing field by field, but found the following 2 differences:
field/property 'address.city' differ:
- actual value : "Tokyo"
- expected value: "Osaka"
...
field/property 'age' differ:
- actual value : 20
- expected value: 21
この後に、比べ方の設定(比較器や、型が違っても比べること)の説明が続きます。
例外のメッセージ違い
Expecting message to be:
"age must be positive"
but was:
"age must be >= 0"
Throwable that failed the check:
java.lang.IllegalArgumentException: age must be >= 0
at …
その他の型
| 判定 | 失敗メッセージ(実際の出力) |
|---|---|
assertThat(List.of(1, 2, 3)).hasSize(2) |
Expected size: 2 but was: 3 in: [1, 2, 3] |
assertThat(List.of("a")).isEmpty() |
Expecting empty but was: ["a"] |
assertThat(" a ").isBlank() |
Expecting blank but was: " a " |
assertThat(Optional.empty()).contains("x") |
Expecting Optional to contain: "x" but was empty. |
assertThat(Map.of("a", 1)).containsEntry("a", 2) |
… but the following map entries had different values: ["a"=1 (expected: 2)] |
assertThat(LocalDate.of(2026, 10, 13)).isBefore(LocalDate.of(2026, 10, 1)) |
Expecting actual: 2026-10-13 (java.time.LocalDate) to be strictly before: 2026-10-01 (java.time.LocalDate) |
assertThatThrownBy(…).isInstanceOf(IllegalStateException.class) |
Expecting actual throwable to be an instance of: java.lang.IllegalStateException but was: java.lang.NumberFormatException: For input string: "x" |
よくある間違い
| 書き方 | 何が起きるか | 直し方 |
|---|---|---|
assertThat(x);(判定メソッドなし) |
何も判定せずに通る | 必ず .isEqualTo(…) などをつなぐ |
assertThat(a).isEqualTo(b).as("説明") |
as が効かない |
as を判定より前に書く |
assertThat(list.size()).isEqualTo(3) |
失敗時にリストの中身が出ない | assertThat(list).hasSize(3) |
assertThat(list.contains("c")).isTrue() |
expected: true but was: false しか出ない |
assertThat(list).contains("c") |
assertThat(0.1 + 0.2).isEqualTo(0.3) |
誤差で失敗 | isCloseTo(0.3, within(1e-9)) |
new SoftAssertions() で assertAll() なし |
失敗が報告されない | 拡張か assertSoftly を使う |
JUnit の assertThat と混ぜて import |
名前がぶつかってコンパイルエラー | AssertJ の Assertions だけを static import |
よくある質問
Q. Hamcrest の assertThat(x, is(y)) と何が違いますか。
A. Hamcrest はマッチャー(is・hasItem など)を引数で渡す形で、AssertJ は assertThat(x) の後ろにメソッドをつなぐ形です。AssertJ は型に合ったメソッドだけが補完で出るので、書ける判定を探しやすいです。
Q. Mockito と一緒に使えますか。
A. 使えます。Mockito でモックを作り、戻り値の判定に AssertJ を使う形がよくあります。引数を取り出して判定する ArgumentCaptor とも組み合わせられます。Mockito の使い方は、関連記事「Mockitoの使い方|JUnit 5での基本からよくあるエラーまで」で扱っています。
Q. Spring Boot のテストでも同じですか。
A. 同じです。spring-boot-starter-test に入っていて、MockMvc の結果を AssertJ で判定する MockMvcTester も Spring Framework に用意されています。Controller のテストは、関連記事「Spring Bootテスト入門|@WebMvcTestとMockMvcの使い分け」で扱っています。
Q. 自分のクラス専用の判定を作れますか。
A. AbstractAssert を継承したクラスを作ると、assertThat(user).hasName("Taro") のような専用のメソッドを足せます。よく使う判定が多いときに向いています。
まとめ
- 形は
assertThat(実際の値).判定(期待値)。JUnit とは引数の順番が逆 - リストは
containsExactly(順番も)・containsExactlyInAnyOrder(順番は問わない)・contains(含む) を使い分ける - 例外は
assertThatThrownBy(…).isInstanceOf(…).hasMessage(…) - オブジェクトのリストは
extracting+tuple、中身の比較はusingRecursiveComparison - 全部の失敗を見たいときは
SoftAssertions(JUnit 5 の拡張でassertAllの呼び忘れを防ぐ) - 失敗メッセージは Expecting actual(実際)… to …(期待) と読む
参考・出典
確認日はいずれも 2026年10月13日です。
- AssertJ 公式ドキュメント:https://assertj.github.io/doc/
- AssertJ(GitHub、ソース・タグ assertj-build-3.27.7):https://github.com/assertj/assertj
- AssertJ Core Javadoc:https://www.javadoc.io/doc/org.assertj/assertj-core/latest/index.html
- Spring Boot ドキュメント「Testing」(Test Scope Dependencies):https://docs.spring.io/spring-boot/reference/testing/test-scope-dependencies.html
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「AssertJの使い方|assertThatの早見表(文字列・リスト・例外・日付)」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。