第07章 実務開発・テスト

07_practical

第07章 実務開発・JUnit・Mockito・例外・ログ【初心者向け改訂版】

この章の読み方: 本文の基本説明、直後の発展解説、例題、演習の順に読んでください。専門用語は初めて出てきた箇所で意味を確認し、コードの予想結果を考えてから実行します。

章末の演習は、それまでの本文の内容を使って解けるように設計しています。

用語の表記: 全10章共通の用語集 と表記を揃えています。

対象:プログラミング未経験者、他言語経験者。前提:第02〜06章でクラス、例外、Maven、HTTPを学習済み。Windows 11、Java 21、Eclipse、Mavenを使用します。MySQLはこの章の最初の実習には不要です。

独学演習: 学んだ内容の確認には、第07章の実行予想・段階別ヒント・自己チェックを使ってください。本文の説明を読んだあと、自分で出力を予想してから試します。

00. この章のゴールと全体像

第06章では、ブラウザやAPIクライアントから送られたHTTPリクエストをSpring Bootが受け取り、Controller、Service、Repositoryへ処理を渡す仕組みを学びました。

しかし、「一度画面に結果が出た」ことと「正しいプログラムができた」ことは同じではありません。入力がゼロの場合、存在しない商品番号を指定した場合、実装を変更した場合など、いろいろな条件で同じ仕様を守れるか確かめる必要があります。

本章ではそれを確認する仕組みを学びます。

以下の順序で進めます。

  1. 仕様を具体的な入力と期待結果に分ける。
  2. 人が操作するテストと自動テストの違いを理解する。
  3. JUnitを使い、正しい結果と間違った結果を検出する。
  4. 失敗させたテストを修正し、再実行する。
  5. MockitoでDBを使わずRepositoryの動きを置き換える。
  6. 例外、HTTPステータス、ログの役割を分けて理解する。
  7. 障害報告とコードレビューに必要な証拠を残す。

合格条件:受講者自身が失敗するテストを再現し、原因を説明し、修正後にmvn testで全テストが成功した証拠を残せること。

さらにMockitoによるDBなしのテスト、ログの確認、仕様に対応するテストケース表を提出できること。Javaコードの説明だけでは合格ではありません。

この節の独学チェック:00. この章のゴールと全体像

確認問題: 品質確認は「動いた」という一回の結果だけで十分ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

正常な入力を1回実行しただけの場合を考えます。

ヒント2

境界値・不正値・既存機能への影響を思い出します。

ヒント3

仕様全体を確認するための別の条件を挙げてください。

模範解答と理由

不十分です。仕様への適合、異常系、境界値、変更前の動作維持も確認します。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 仕様への適合、異常系、境界値、変更前の動作維持も確認します。

満点の正答例: 不十分です。仕様への適合、異常系、境界値、変更前の動作維持も確認します。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「仕様への適合、異常系、境界値、変更前の動作維持も確認します」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「00. この章のゴールと全体像」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

01. そもそも「品質」とは何か

ソフトウェアの品質とは、単にエラーを表示せずに動くことだけではありません。仕様で決めた計算結果になること、間違った入力を安全に拒否すること、あとで変更しても以前の機能を壊さないこと、問題が起こったとき調査できることが大切です。

例えば100円の商品を税込110円で返せたとしても、99円の商品を税込109円で返してしまうなら端数処理の仕様を満たしていません。そこで「どんな入力なら、どんな結果が正解なのか」を最初に書きます。

理解を深める:一度動いただけでは品質を保証できない理由

税込計算が100円で正しくても、0円、非常に大きな金額、負数にどう対応するかはまだ分かりません。実務では仕様と期待結果を先に決めてからテストする必要があります。

例えば「負の単価は拒否する」と仕様で決めたなら、負数入力で仕様どおりの拒否結果になるかを確認します。内部の単体テストでは例外、Web APIではHTTP 400など、確認する層によって期待結果の表し方は異なります。

仕様が曖昧なら勝手に正解を決めず確認事項として記録します。

この節の独学チェック:01. そもそも「品質」とは何か

確認問題: 正常系が通っただけでバグがないと言えますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

一つの成功例が証明できる範囲を考えましょう。

ヒント2

数量0や非常に大きい値でも同じか予想します。

ヒント3

未検証の入力が残ることを根拠に答えます。

模範解答と理由

言えません。正常入力以外の条件や極端な値も検証が必要です。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 正常入力以外の条件や極端な値も検証が必要です。

満点の正答例: 言えません。正常入力以外の条件や極端な値も検証が必要です。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「正常入力以外の条件や極端な値も検証が必要です」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「01. そもそも「品質」とは何か」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

02. 仕様書からテストケースを考える

本章の税込価格計算の仕様は次のとおりです。入力は0以上の整数で表した税抜価格(円)。税率は10%。1円未満は切り捨てます。負の金額はIllegalArgumentExceptionで拒否します。

計算結果がintの範囲を超える場合、黙って数値を丸めず例外にします。この最後の条件は演習用に明示した設計です。実務では巨大な金額に対する扱いを仕様書で決める必要があります。

入力 期待結果 分類 確認したいこと
-1 IllegalArgumentException 異常系 不正入力の拒否
0 0 境界値 下限ぴったり
1 1 境界値 端数の切り捨て
99 108 正常系 108.9を切り捨て
100 110 正常系 端数のない計算
101 111 正常系 111.1を切り捨て
2147483647 ArithmeticException 異常系 あふれの検出

「正常系」は仕様で受け付ける入力、「異常系」は拒否・失敗すべき入力です。「境界値」は許容範囲の境目とその直前・直後の値を指します。境界には誤りが入り込みやすいため、意識して試します。

理解を深める:テストケースを設計する順番

条件 入力 期待される動作の例 何を検証するか
正常 単価100円 税率・端数規則に従って計算 通常処理
境界 単価0円 仕様上許すなら0円 ちょうど境界の値
異常 単価-1円 規定の例外 不正データの排除

上表は学習のための例で、課題の税込金額の正解値は指定された税率・端数処理規則に従って決めてください。根拠のない期待値をテストに書くと、誤った実装を正解と判定する危険があります。

理解を深める:テストに先に期待結果を書く理由

バグ修正前にテストを書いて失敗させれば、どの不具合を直したのかが明確になります。修正後に同じテストが成功すれば、その不具合について再発を検出する仕組みも残ります。

最初から成功するテストしかないと、問題を見落としたまま修正済みだと勘違いする恐れがあります。第09章でも現象記録→失敗再現→修正→再検証を繰り返します。

この節の独学チェック:02. 仕様書からテストケースを考える

確認問題: 数量の仕様が1〜10なら、境界値として何を試しますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

仕様の下限1と上限10を数直線に置きましょう。

ヒント2

境界のちょうど内側と一つ外側に注目します。

ヒント3

下限の外・下限・上限・上限の外を4つ並べます。

模範解答と理由

0、1、10、11を確認します。範囲外と範囲内の境界を確かめるためです。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: 下限の外と境界として0、1を挙げる。
  2. 1点: 上限の境界と外として10、11を挙げる。

満点の正答例: 0、1、10、11を確認します。範囲外と範囲内の境界を確かめるためです。

部分点の判定: 部分正答例:「下限の外と境界として0、1を挙げる」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「下限の外と境界として0、1を挙げる」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「02. 仕様書からテストケースを考える」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

図解:仕様からテストを作る

仕様からテストを作る

図の読み方:テストは仕様から入力条件と期待結果を定義して判定します。

03. JUnitの前に、手で確かめる

プログラムを実行して画面に結果を表示する方法は「手動テスト」です。最初は十分役立ちますが、修正のたびに同じ操作を繰り返すのは手間がかかります。人によって確認し忘れる項目も変わります。

自動テストは、入力と期待結果をプログラムとして残し、何度でも同じ条件で実行する方法です。テストが成功しただけで仕様全体の正しさが証明されるわけではありません。テストに書いた条件について確認できたと理解しましょう。

この節の独学チェック:03. JUnitの前に、手で確かめる

確認問題: JUnitを使う前に、期待値を決めるのはなぜですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

出力結果を見てから正解を決めると何が起こるでしょうか。

ヒント2

テストの期待値の根拠を仕様に戻して考えます。

ヒント3

誤った実装を正解扱いしないための順序を説明します。

模範解答と理由

実際の出力に合わせて都合よく期待値を変えることを防ぎ、仕様に基づく判定をするためです。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 実際の出力に合わせて都合よく期待値を変えることを防ぎ、仕様に基づく判定をするためです。

満点の正答例: 実際の出力に合わせて都合よく期待値を変えることを防ぎ、仕様に基づく判定をするためです。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「実際の出力に合わせて都合よく期待値を変えることを防ぎ、仕様に基づく判定をするためです」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「03. JUnitの前に、手で確かめる」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

04. 配布プロジェクトとEclipseへの取り込み

教材ZIPを展開したら examples/07_practical/pricing フォルダーを探します。この中のpom.xmlはMavenの設定ファイルです。

src/main/javaは製品コード、src/test/javaはテストコードの置き場所です。2つの場所が分かれているので、テストのためだけに製品コードを変更せずに検証できます。

  1. Eclipseを起動し、File→Import...を選びます。
  2. Maven→Existing Maven Projectsを選び、Nextを押します。
  3. Root Directoryに展開したpricingフォルダーを指定し、pom.xmlが検出されることを確認します。
  4. Finishで取り込みます。初回はライブラリ取得で時間がかかる場合があります。
  5. プロジェクトのJRE System LibraryがJava 21か確認します。
  6. PriceService.javaとPriceServiceTest.javaが異なるソースフォルダーに存在するか確認します。

Eclipseのメニュー名はバージョンによって多少異なります。取り込みに失敗したら、まず選択したフォルダーにpom.xmlがあるか、Java 21が設定されているかを確かめます。

ネット接続が使えないと依存ライブラリの初回取得が失敗します。その場合はJavaのプログラムの誤りだと決めつけず、エラー全文を記録します。

この節の独学チェック:04. 配布プロジェクトとEclipseへの取り込み

確認問題: テスト失敗時に最初に読むべき情報は何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

失敗メッセージにテスト名が含まれることがあります。

ヒント2

expectedとactualを区別してください。

ヒント3

例外のスタックトレースから最初の調査箇所を考えます。

模範解答と理由

どのテストが失敗したか、期待値と実際値、例外の発生位置を確認します。

この節の自己採点基準(3点満点)

独立して判定する正答要素

  1. 1点: 失敗したテスト名を確認する。
  2. 1点: 期待値と実際値を比較する。
  3. 1点: 例外発生箇所を調べる。

満点の正答例: どのテストが失敗したか、期待値と実際値、例外の発生位置を確認します。

部分点の判定: 部分正答例:「失敗したテスト名を確認する」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「失敗したテスト名を確認する」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:3/3点。 正答の言い換えは認めます。

復習先: この節「04. 配布プロジェクトとEclipseへの取り込み」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

05. Mavenコマンドを実行する

WindowsのPowerShellを開き、pricingフォルダーに移動します。エクスプローラーでフォルダーを開き、アドレスバーにpowershellと入力してEnterを押しても構いません。

次のコマンドはpom.xmlがあるフォルダーで実行します。

java -version
mvn -version
mvn test

最初の2つはJavaとMavenが使用できるか確認する命令です。mvn testは、Mavenにテストの実行を依頼します。成功時は最後の方にBUILD SUCCESSが表示されます。

テストが0件の場合は学習上成功扱いにしないでください。target/surefire-reportsに結果が作成されるので、実行数、失敗数、エラー数を確認しましょう。

PowerShellでmvnが見つからない場合は第01章の環境変数設定を見直してください。

この節の独学チェック:05. Mavenコマンドを実行する

確認問題: mvn testで依存ライブラリを取得できなかった場合、業務ロジックが間違いだと判断できますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

テストに到達できない段階の失敗を考えます。

ヒント2

ライブラリ取得エラーとassertの不一致は別物です。

ヒント3

環境・ネットワーク・Maven設定を確認してからロジックを疑います。

模範解答と理由

できません。ビルド環境・ネットワーク・リポジトリ設定の問題とテストの失敗を区別します。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: ビルド環境・ネットワーク・リポジトリ設定の問題とテストの失敗を区別します。

満点の正答例: できません。ビルド環境・ネットワーク・リポジトリ設定の問題とテストの失敗を区別します。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「ビルド環境・ネットワーク・リポジトリ設定の問題とテストの失敗を区別します」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「05. Mavenコマンドを実行する」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

06. 最初のJUnitテストを読む

src/test/java/training/pricing/PriceServiceTest.javaを開いてください。例えば次のテストがあります。

@Test
void hundredYenHasNoFraction() {
    assertEquals(110, service.taxIncluded(100));
}

@Testは「このメソッドをテストとして実行する」というJUnitへの目印です。voidは呼び出し元へ値を返さないことを意味します。

hundredYenHasNoFractionは人が読んで内容を推測できるメソッド名です。service.taxIncluded(100)は実際に検証したい処理を呼び出します。

assertEquals(110, ...)は「期待する110と計算結果が等しいか確認する」という命令です。異なる場合、そのテストは失敗します。

経験者向け補足: JUnitのassertはJavaのassert文とは異なるAPIです。実行オプション-eaを必要としません。自動テストの期待値を仕様から独立して考える点は、どの言語でも重要です。

理解を深める:テスト結果から判断できるのは検証した条件の範囲だけ

一度商品登録が成功しても、価格が0、負数、上限付近という条件で同じ結果になるとは限りません。テストを作る理由は、仕様を入力と期待結果に分解して何を確かめたかの記録を残すことです。

テストに通ったからすべて正しいと断言するのではなく、「この条件でこの結果になった」と説明することが大切です。

この節の独学チェック:06. 最初のJUnitテストを読む

確認問題: assertEquals(110,actual)が失敗しactual=100の場合、何を調べますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

expected 110とactual 100を数字として比べます。

ヒント2

税率や端数処理を含む仕様を確認します。

ヒント3

仕様の計算式を紙で再現してどちらが妥当か判定します。

模範解答と理由

期待値110となる仕様、実際の計算方法と税率・丸め方を確認します。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 期待値110となる仕様、実際の計算方法と税率・丸め方を確認します。

満点の正答例: 期待値110となる仕様、実際の計算方法と税率・丸め方を確認します。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「期待値110となる仕様、実際の計算方法と税率・丸め方を確認します」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「06. 最初のJUnitテストを読む」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

07. あえてテストを失敗させる(必須)

受講者自身が失敗を体験します。まずmvn testが成功することを確認します。

その後src/main/java/training/pricing/PriceService.javaのnew BigDecimal("1.10")を一時的にnew BigDecimal("1.08")へ変えます。

ファイルを保存して再度mvn testを実行してください。

99円のテストなら期待108円なのに実際は106円となり、テストが失敗するはずです。表示内容から「期待値(expected)」と「実際値(actual)」を探して記録してください。

この時点で表示されるBUILD FAILUREは実習で意図した結果です。

失敗を見たら1.10に戻し、保存してmvn testを再実行します。すべて成功することを確認してください。変更を戻す前に次の演習へ進まないでください。

この節の独学チェック:07. あえてテストを失敗させる(必須)

確認問題: テストをわざと失敗させた後、何をして完了としますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

失敗時と修正後で同じテストを使いましょう。

ヒント2

例外や不一致の根本原因を調べます。

ヒント3

修正した箇所以外も動作するか関連テストを考えてください。

模範解答と理由

原因を確認し、修正後に同じテストと関連テストを再実行して通ることを確認します。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 原因を確認し、修正後に同じテストと関連テストを再実行して通ることを確認します。

満点の正答例: 原因を確認し、修正後に同じテストと関連テストを再実行して通ることを確認します。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「原因を確認し、修正後に同じテストと関連テストを再実行して通ることを確認します」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「07. あえてテストを失敗させる(必須)」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

08. assertThrowsで例外を確認する

異常な入力を指定した場合は、期待した種類の例外が発生することをテストします。

@Test
void negativePriceIsRejected() {
    IllegalArgumentException error = assertThrows(
        IllegalArgumentException.class,
        () -> service.taxIncluded(-1)
    );
    assertTrue(error.getMessage().contains("0以上"));
}

assertThrowsの1番目の引数には期待する例外のクラスを書きます。2番目の() -> ...は、その時点では処理を実行せず、JUnitへ「実行する処理」を渡すラムダ式です。

ここで即座にservice.taxIncluded(-1)の結果を渡してしまうと意図どおりに動きません。戻り値errorを使えば例外の説明文も検査できます。例外文言そのものの厳密一致が必要かは製品仕様で決めます。

この節の独学チェック:08. assertThrowsで例外を確認する

確認問題: assertThrowsで確認したいのは何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

引数に指定する例外クラスを確認します。

ヒント2

例外がまったく起こらない場合を想像してください。

ヒント3

期待する型の例外が処理から送出されたかどうかを調べます。

模範解答と理由

指定した処理が期待する例外型を投げることです。例外が起きない場合もテスト失敗になります。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: 指定した処理が期待する例外型を投げることです。
  2. 1点: 例外が起きない場合もテスト失敗になります。

満点の正答例: 指定した処理が期待する例外型を投げることです。例外が起きない場合もテスト失敗になります。

部分点の判定: 部分正答例:「指定した処理が期待する例外型を投げることです」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「指定した処理が期待する例外型を投げることです」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「08. assertThrowsで例外を確認する」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

09. 金額計算とBigDecimal

PriceServiceでは浮動小数点型のdoubleではなくBigDecimalを使います。0.1などの小数は2進数で正確に表現できない場合があります。

BigDecimal.valueOf(original)で金額を作り、multiplyで税率を掛け、setScale(0, RoundingMode.DOWN)で小数点以下を切り捨てます。

intValueExact()は正確にintに変換できない場合に例外を発生させるため、意図せず巨大な値を返すことを防ぎます。

注意点として、実務の税計算は軽減税率、行単位か合計単位か、四捨五入など、業務ごとに仕様が異なります。この教材の計算式をすべての業務システムでそのまま使用してはいけません。

この節の独学チェック:09. 金額計算とBigDecimal

確認問題: お金の計算でdoubleではなくBigDecimalを選ぶ理由は何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

0.1を二進浮動小数点で表すとどうなるでしょうか。

ヒント2

金額に必要な十進精度と丸め規則を考えます。

ヒント3

BigDecimalのコンストラクタの引数にも注意します。

模範解答と理由

doubleでは0.1などの十進小数を正確に表せない場合があります。BigDecimalを十進文字列などから生成すると、十進数の値を正確に表し、桁数と丸め方法を明示して計算できます。なおBigDecimal.valueOf(double)など生成方法にも注意が必要です。

この節の自己採点基準(3点満点)

独立して判定する正答要素

  1. 1点: doubleは十進小数を常に厳密に表現できるわけではないと説明する。
  2. 1点: BigDecimalなら十進の値と丸めを明示できると説明する。
  3. 1点: BigDecimalの生成方法に注意すると答える。

満点の正答例: doubleでは0.1などの十進小数を正確に表せない場合があります。BigDecimalを十進文字列などから生成すると、十進数の値を正確に表し、桁数と丸め方法を明示して計算できます。なおBigDecimal.valueOf(double)など生成方法にも注意が必要です。

部分点の判定: 部分正答例:「doubleは十進小数を常に厳密に表現できるわけではないと説明する」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「doubleは十進小数を常に厳密に表現できるわけではないと説明する」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:3/3点。 正答の言い換えは認めます。

復習先: この節「09. 金額計算とBigDecimal」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

10. テストの独立性と準備

テストが他のテストの結果に依存すると、実行順を変えたとき失敗します。例えば「最初に商品を登録するテスト」を実行しないと「商品を取得するテスト」が成功しない設計は避けます。

各テストは自身に必要なデータを準備し、必要なら後片付けします。この章のProductLookupServiceTestは各テストで新しいモックを作るため、別のテストの実行結果を前提としません。

この節の独学チェック:10. テストの独立性と準備

確認問題: テスト間で同じ変更可能なListを共有すると何が困りますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

Listの中身を変更するテストが2本あると仮定します。

ヒント2

2本目が1本目の結果に依存してよいでしょうか。

ヒント3

テスト順序を逆にした場合の結果を考えます。

模範解答と理由

先行テストの変更が後続テストに影響し、実行順序によって結果が変わるおそれがあります。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 先行テストの変更が後続テストに影響し、実行順序によって結果が変わるおそれがあります。

満点の正答例: 先行テストの変更が後続テストに影響し、実行順序によって結果が変わるおそれがあります。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「先行テストの変更が後続テストに影響し、実行順序によって結果が変わるおそれがあります」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「10. テストの独立性と準備」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

11. ServiceとRepositoryの役割を思い出す

第06章のWebアプリではControllerがHTTP要求を受け取り、Serviceが業務処理を行い、Repositoryがデータを扱います。

ServiceをテストするたびにMySQLを起動しなければならないと、DB障害とServiceの不具合が混ざります。そこで「Repositoryとして呼び出せるもの」をテスト用に用意し、Serviceだけを調べる方法を学びます。

本章のProductGatewayは、データ取得の約束を定義したインターフェースです。

ProductLookupServiceは具体的なDB接続方法を知らず、ProductGatewayのfindByIdを呼びます。この設計は第03章のインターフェース、第06章のDIを復習する材料にもなります。

この節の独学チェック:11. ServiceとRepositoryの役割を思い出す

確認問題: Serviceの単体テストでRepositoryを差し替える狙いは何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

Serviceの条件分岐だけを試したいと考えます。

ヒント2

DBの値が変化するとテストの再現性はどうなるでしょうか。

ヒント3

Repositoryに代替実装を渡す効果を説明します。

模範解答と理由

DBの状態に左右されず、Serviceの条件分岐や処理を独立して確認するためです。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: DBの状態に左右されず、Serviceの条件分岐や処理を独立して確認するためです。

満点の正答例: DBの状態に左右されず、Serviceの条件分岐や処理を独立して確認するためです。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「DBの状態に左右されず、Serviceの条件分岐や処理を独立して確認するためです」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「11. ServiceとRepositoryの役割を思い出す」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

12. Mockitoとは何か

Mockitoはテスト用の代役(モック)を作るライブラリです。モックを使うと、実際のDBを呼ばずに「商品1番は存在する」「商品99番は見つからない」という結果を再現できます。モックは本物のDBの正しさを保証しません。

Serviceの処理を独立して調べるための道具です。

ProductGateway gateway = mock(ProductGateway.class);
Product expected = new Product(1L, "ノート", 120);
when(gateway.findById(1L)).thenReturn(Optional.of(expected));
Product actual = new ProductLookupService(gateway).find(1L);
assertEquals(expected, actual);
verify(gateway).findById(1L);

1行目はRepository役の代役を作っています。2行目はテストで返してほしい商品を準備します。3行目は「ID 1を検索したら商品を返す」と約束します。4行目はその代役を渡してServiceを実行します。

5行目は結果の正しさを検証します。6行目はID 1を使ってRepositoryが呼ばれた事実を確認します。

verifyは動作確認に役立ちますが、呼び出し回数を細かく固定しすぎると、動作が同じでも内部の整理だけでテストが壊れることがあります。

理解を深める:Mockitoを使う理由と使いすぎない理由

Serviceの単体テストでは、MySQLが動いていなくても「商品が存在しなかったとき」の処理を確認したいことがあります。MockitoのモックはRepositoryの振る舞いを指定して代役にできます。

一方、モックだけのテストではSQLの正しさや本物のDBの動きは確認できません。単体テストと結合テストは互いを置き換えないため、役割を区別して使います。

理解を深める:なぜMockitoでRepositoryを置き換えるのか

Serviceの計算結果を確認したいだけなのに、DBを起動し、テストデータを毎回登録するのは手間がかかります。MockitoでRepositoryの代役(モック)を用意すると、DBがどう応答するかをテストの中で決められます。

こうするとServiceの分岐・計算・呼び出し回数を狙って調べやすくなります。ただしモックテストだけでは、本物のSQLや設定が正しいことは確認できません。そのため単体テストと結合テストを使い分けます。

この節の独学チェック:12. Mockitoとは何か

確認問題: Mockitoのwhen(...).thenReturn(...)は何を指定しますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

whenの対象となるメソッド呼び出しを確認します。

ヒント2

そのメソッドを呼んだ後に何を返すかに注目します。

ヒント3

実物のDBを使わず返却値を固定する場面を考えます。

模範解答と理由

モックのメソッドが呼ばれたときに返す値を指定します。実DBアクセスの代わりを作れます。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: モックのメソッドが呼ばれたときに返す値を指定します。
  2. 1点: 実DBアクセスの代わりを作れます。

満点の正答例: モックのメソッドが呼ばれたときに返す値を指定します。実DBアクセスの代わりを作れます。

部分点の判定: 部分正答例:「モックのメソッドが呼ばれたときに返す値を指定します」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「モックのメソッドが呼ばれたときに返す値を指定します」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「12. Mockitoとは何か」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

図解:Mockitoで依存先を置き換える

Mockitoで依存先を置き換える

図の読み方:モックを使うと外部依存を置き換え、Serviceを単独でテストできます。

13. 存在しない商品・不正な商品ID

ProductLookupServiceはIDが0以下なら入力エラーとしてIllegalArgumentExceptionを投げます。

IDが正しくても商品が存在しない場合はProductNotFoundExceptionを投げます。この2種類を区別すると、Web API側では前者を400、後者を404へ変換する設計ができます。

重要:本章のpricingプロジェクトはHTTPサーバーではありません。ここではService内部の例外のテストを行います。HTTPステータスそのものの確認は第06章のSpring Bootプロジェクトで別途行います。

この節の独学チェック:13. 存在しない商品・不正な商品ID

確認問題: 存在しない商品IDで何を確認しますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

存在しないIDを渡したときの仕様を読みましょう。

ヒント2

見つからない結果とサーバー障害を区別します。

ヒント3

そのAPI・Serviceが定める戻り値や例外と一致するか確認します。

模範解答と理由

見つからないことを適切に扱い、仕様に沿う例外や結果を返すことを確認します。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 見つからないことを適切に扱い、仕様に沿う例外や結果を返すことを確認します。

満点の正答例: 見つからないことを適切に扱い、仕様に沿う例外や結果を返すことを確認します。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「見つからないことを適切に扱い、仕様に沿う例外や結果を返すことを確認します」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「13. 存在しない商品・不正な商品ID」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

14. Mockitoで「呼ばれてはいけない」を確認する

入力IDが0なら、DBへの問い合わせを始める前に拒否したいはずです。次のテストでは、不正なIDのときRepositoryがまったく呼ばれていないことを確認します。

ProductGateway gateway = mock(ProductGateway.class);
ProductLookupService service = new ProductLookupService(gateway);
assertThrows(IllegalArgumentException.class, () -> service.find(0));
verifyNoInteractions(gateway);

エラーメッセージだけを確認するより、不要なデータアクセスが起きていないことまで確かめられます。

この節の独学チェック:14. Mockitoで「呼ばれてはいけない」を確認する

確認問題: Mockitoのverify(...,never())は何を確認しますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

不正入力の際に保存処理へ進むべきでしょうか。

ヒント2

verifyに渡された呼び出しを調べてください。

ヒント3

neverが回数0を表すことから、何を禁止するか考えます。

模範解答と理由

指定したメソッドが呼ばれていないことを確認します。不正入力時のDB操作禁止などに使います。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: 指定したメソッドが呼ばれていないことを確認します。
  2. 1点: 不正入力時のDB操作禁止などに使います。

満点の正答例: 指定したメソッドが呼ばれていないことを確認します。不正入力時のDB操作禁止などに使います。

部分点の判定: 部分正答例:「指定したメソッドが呼ばれていないことを確認します」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「指定したメソッドが呼ばれていないことを確認します」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「14. Mockitoで「呼ばれてはいけない」を確認する」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

15. ログとは何か、printlnとは何が違うのか

System.out.printlnは学習中に値を確認するのに便利です。一方、実務ではいつ・どの種類の事象が発生したかを後から調べる必要があります。ログには通常、発生日時、ログレベル、出力元、説明を付けます。

INFOは通常の処理経過、WARNING(SpringのSLF4JではWARN)は注意すべき事象、SEVERE(SpringではERROR)は処理失敗などを表します。

本章の独立したJavaサンプルは、追加ライブラリが不要なjava.util.logging.Loggerを使用しています。Spring Bootの本番アプリでは一般にSLF4Jを利用します。

この2つのAPIを混同しないようにしてください。

理解を深める:ログを出す理由

システムが止まった際、「何時にどの処理で何が起きたか」を後から調べるためです。System.out.println は簡単ですが、実務ではレベル、出力先、識別情報を統一できるロガーを利用します。

パスワード、認証情報、個人情報を無条件に出力してはいけません。例外のスタックトレースを記録する場合も、公開範囲と秘密情報に注意します。

理解を深める:ログと例外は何が違うのか

例外はプログラムが通常どおり処理できない事態を呼び出し元へ伝える仕組みです。ログは「いつ、どの処理で、何が起きたか」を後で調査するための記録です。例外を出しただけで、必要な調査情報がすべて残るわけではありません。

逆にログを書いただけで、不正な処理が自動的に止まるわけでもありません。パスワード・個人情報・認証トークンなどをログへそのまま出力しないことも重要です。

この節の独学チェック:15. ログとは何か、printlnとは何が違うのか

確認問題: System.out.printlnとロギングライブラリは実務上何が違いますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

printlnが出せる情報と制御機能を比較します。

ヒント2

INFO・ERRORなどのレベルを想像してください。

ヒント3

本番運用で出力先やレベルを変更する場面を考えます。

模範解答と理由

ロギングはレベルや出力先を設定しやすく、障害調査に必要な情報を管理できます。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: ロギングはレベルや出力先を設定しやすく、障害調査に必要な情報を管理できます。

満点の正答例: ロギングはレベルや出力先を設定しやすく、障害調査に必要な情報を管理できます。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「ロギングはレベルや出力先を設定しやすく、障害調査に必要な情報を管理できます」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「15. ログとは何か、printlnとは何が違うのか」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

16. ログを実際に出力して読む

EclipseでLogPracticeMain.javaを右クリックし、Run As→Java Applicationを選びます。

Java 21が使えるコマンドラインなら、pricingフォルダーで次のようにも実行できます。

javac -encoding UTF-8 -d target/manual src/main/java/training/pricing/*.java
java -cp target/manual training.pricing.LogPracticeMain

PowerShellでは*.javaの展開方法が環境によって異なる場合があります。上記のjavacにワイルドカード関連のエラーが出る場合は、EclipseからJava Applicationで起動してください。

成功すると商品の検索開始と成功がログに記録され、存在しない商品ID 999の検索時には例外メッセージが画面に表示されます。ログ表示の時刻・順番は環境によって多少異なります。

※ パスワード、APIキー、個人情報、認証トークンをログに出してはいけません。入力をそのままログに入れる場合は、改行などによりログの読み取りを妨げないようにも注意します。

この節の独学チェック:16. ログを実際に出力して読む

確認問題: ログに出してよい情報と避けるべき情報の例を挙げてください。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

障害調査に必要な識別子を挙げてください。

ヒント2

利用者のパスワードがログに残る場合を想像します。

ヒント3

役立つ運用情報と漏えいリスクを別々に判断します。

模範解答と理由

処理ID・検査結果などは有用ですが、パスワードや機密情報の無条件出力は避けます。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: ログには処理IDや検査結果など調査に必要な情報を出す。
  2. 1点: パスワードや機密情報を無条件に出力しない。

満点の正答例: 処理ID・検査結果などは有用ですが、パスワードや機密情報の無条件出力は避けます。

部分点の判定: 部分正答例:「ログには処理IDや検査結果など調査に必要な情報を出す」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「ログには処理IDや検査結果など調査に必要な情報を出す」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「16. ログを実際に出力して読む」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

17. HTTPステータスとアプリ内部の例外

Javaの例外が発生しただけで必ずHTTP 404になるわけではありません。

Spring MVC側で「この例外は404へ変換する」という処理(例:@RestControllerAdviceと@ExceptionHandler)を実装する必要があります。

実務では4xx(入力や対象指定の問題)と5xx(サーバー側の障害)を区別します。内部例外のスタックトレースやSQL全文は、クライアントへそのまま公開せず、適切な範囲でログに残します。

発展演習:第06章のSpring Bootアプリで「商品ID 999を取得したら404」の仕様を追加し、JUnitでWeb層をテストします。これは本章の独立したpricingサンプルには完成実装として含めていません。

この節の独学チェック:17. HTTPステータスとアプリ内部の例外

確認問題: Java内部でIllegalArgumentExceptionが起きたら必ずHTTP 500ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

Javaの例外クラス名とHTTPの状態は別の概念です。

ヒント2

例外をControllerAdvice等で変換する場合を考えます。

ヒント3

入力の誤りとして処理できる場合のステータスを調べます。

模範解答と理由

必ずではありません。例外を適切にHTTP 400などに変換するかはAPIの設計次第です。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: 必ずではありません。
  2. 1点: 例外を適切にHTTP 400などに変換するかはAPIの設計次第です。

満点の正答例: 必ずではありません。例外を適切にHTTP 400などに変換するかはAPIの設計次第です。

部分点の判定: 部分正答例:「必ずではありません」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「必ずではありません」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「17. HTTPステータスとアプリ内部の例外」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

18. 障害調査の実務的な順番

不具合を見たら、最初から無関係なコードを修正しないでください。まずどの入力と操作で起きるか、期待値と実測値に違いがあるかを記録します。

次に再現性を確かめ、処理の入口(Controllerやmain)から入力の流れを追い、例外やログを確認します。原因の仮説を一つ立て、最小限の変更を加え、対象のテストだけでなく既存のテストも再実行します。

修正結果を第三者が検証できる形で残すまでが作業です。

理解を深める:テストが失敗したときの考え方

最初に期待値・実際値・再現条件を分けて書きます。次に、仕様が誤っているのか、テストデータが誤っているのか、実装が誤っているのかを切り分けます。「テストを緑にするために期待値を修正する」のは、仕様の再確認なしには行いません。

この節の独学チェック:18. 障害調査の実務的な順番

確認問題: 障害調査では、最初に何を再現・確認しますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

再現できない不具合を直す難しさを考えます。

ヒント2

入力・時刻・手順・影響範囲の情報を揃えます。

ヒント3

原因の推測より先に確定すべき観測事実を書き出します。

模範解答と理由

発生条件、入力、再現手順、ログ時刻、影響範囲を揃えてから原因を絞り込みます。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: 入力・再現手順を確認する。
  2. 1点: ログ時刻・影響範囲を確認する。

満点の正答例: 発生条件、入力、再現手順、ログ時刻、影響範囲を揃えてから原因を絞り込みます。

部分点の判定: 部分正答例:「入力・再現手順を確認する」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「入力・再現手順を確認する」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「18. 障害調査の実務的な順番」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

図解:障害調査の流れ

障害調査の流れ

図の読み方:不具合の再現条件と根本原因を特定してから修正・再検証します。

19. 回帰テストと変更差分

修正した機能は正しくなっても、別の機能を壊すことがあります。修正後に既存のテストをもう一度実行することを回帰テストと呼びます。Gitが使える場合はgit diffで変更箇所を見ます。

意図的なテスト失敗のために変えた税率や、デバッグのためのprintlnを残していないか確認しましょう。

この節の独学チェック:19. 回帰テストと変更差分

確認問題: 一箇所を修正した後に関連機能もテストする理由は何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

変更箇所を通る別の処理がないか探します。

ヒント2

修正前に成功していたテストをもう一度動かします。

ヒント3

修正が既存動作を壊していないか確かめる目的を答えます。

模範解答と理由

変更により以前動いていた別の処理が壊れていないかを確認する回帰テストのためです。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 変更により以前動いていた別の処理が壊れていないかを確認する回帰テストのためです。

満点の正答例: 変更により以前動いていた別の処理が壊れていないかを確認する回帰テストのためです。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「変更により以前動いていた別の処理が壊れていないかを確認する回帰テストのためです」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「19. 回帰テストと変更差分」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

20. 作業報告書の書き方

受講者は「環境:Java 21 / Windows 11」「実行コマンド:mvn test」「期待:税抜99円→税込108円」「実測:税率を変えたとき106円となりテスト失敗」「原因:税率1.08へ一時変更」「対処:1.10へ復旧」「再実行:全件成功」のように事実を整理します。

画面に表示されたテスト数も記録します。成功していないのに成功と書くことは禁止です。

この節の独学チェック:20. 作業報告書の書き方

確認問題: テスト報告書には成功と書くだけで十分ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

「成功」の判断根拠を第三者へ渡す状況を考えます。

ヒント2

どの環境でどんな期待値を試したでしょうか。

ヒント3

手順・期待・実際・未実施事項を記録する意味を考えます。

模範解答と理由

不十分です。実行手順、期待結果、実際結果、実施環境、未実施事項も記載します。

この節の自己採点基準(3点満点)

独立して判定する正答要素

  1. 1点: 実施環境と実行手順を記載する。
  2. 1点: 期待値と実結果を記載する。
  3. 1点: 未実施項目を記載する。

満点の正答例: 不十分です。実行手順、期待結果、実際結果、実施環境、未実施事項も記載します。

部分点の判定: 部分正答例:「実施環境と実行手順を記載する」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「実施環境と実行手順を記載する」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:3/3点。 正答の言い換えは認めます。

復習先: この節「20. 作業報告書の書き方」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

21. 受講者演習への進み方

exercises/07_practical/assignment.mdの課題1から順番に行ってください。課題の途中で仕様が分からなくなったら、本章の仕様表に戻ります。

JUnitが動かない場合、JDKだけで確認できるverification/RunWithoutMaven.javaも用意していますが、こちらは補助確認であり、JUnitの合格条件の代わりではありません。

この節の独学チェック:21. 受講者演習への進み方

確認問題: 演習でテストが失敗した場合、先に模範解答を写すべきですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

テストの期待値を見直す前に仕様を確認します。

ヒント2

まず失敗の差分を観察してください。

ヒント3

ヒントを順に使った後に模範解答を参照する順序を考えます。

模範解答と理由

まず期待値と実際値・原因を調べ、必要なら段階的ヒントを使い、最後に解答を確認します。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: まず期待値と実際値・原因を調べ、必要なら段階的ヒントを使い、最後に解答を確認します。

満点の正答例: まず期待値と実際値・原因を調べ、必要なら段階的ヒントを使い、最後に解答を確認します。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「まず期待値と実際値・原因を調べ、必要なら段階的ヒントを使い、最後に解答を確認します」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「21. 受講者演習への進み方」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

22. よくあるトラブル

症状 まず確認すること 対処の考え方
mvnが見つからない MavenのインストールとPATH 第01章に戻る
package org.junit.jupiter.api does not exist Mavenの依存取得とsrc/test/javaの位置 Mavenプロジェクトとして取り込み直す
Mockitoで例外が出る Javaバージョンと依存取得状況 例外全文を保存し環境要因を切り分ける
テストが0件 Surefire設定とテストクラス名 *Test.javaを確認
BUILD FAILURE 失敗が意図したものか expected/actualと変更箇所を確認
javacの文字化け ファイルがUTF-8か -encoding UTF-8を指定
Spring Bootが起動しない 本章のpricingはWebサーバーではない 第06章のプロジェクトで起動

この節の独学チェック:22. よくあるトラブル

確認問題: テストが見つからない場合、業務コードを書き直す前に何を確認しますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

テストを実行したのに0件になった状況を想像します。

ヒント2

src/test/javaやテストクラス名に注目します。

ヒント3

MavenとJUnitの検出設定を業務ロジックと区別します。

模範解答と理由

テストファイルの配置、パッケージ、テスト用依存ライブラリとMaven設定を確認します。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: テストファイルの配置、パッケージ、テスト用依存ライブラリとMaven設定を確認します。

満点の正答例: テストファイルの配置、パッケージ、テスト用依存ライブラリとMaven設定を確認します。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「テストファイルの配置、パッケージ、テスト用依存ライブラリとMaven設定を確認します」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「22. よくあるトラブル」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

23. 理解度チェック

  1. テストの期待値はどこから決めますか。
  2. assertEqualsとassertThrowsは何を確かめますか。
  3. テストを一度失敗させる意味は何ですか。
  4. なぜServiceの単体テストでは実DBを使わない場合がありますか。
  5. mock、when、verifyはそれぞれ何をする命令ですか。
  6. 404と500の違いは何ですか。
  7. INFOログにパスワードを書いてもよいですか。
  8. 修正後に既存テストを再実行するのはなぜですか。
  9. mvn testが成功でも、テスト0件ならなぜ不合格ですか。
  10. 不具合報告で「何となく動かない」だけでは足りない理由は何ですか。

理解を深める:必要なテストの範囲を考える

「価格100円の商品は正しい」の1件だけでは不十分です。価格0円という下限、負の価格という拒否条件、非常に大きな価格、見つからない商品、依存先の障害などを整理します。

仕様の境界と分岐を基準にテストを選べば、根拠を持ってレビューできます。

この節の独学チェック:23. 理解度チェック

確認問題: 単体テストと結合テストは何を違えて確認しますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

Service単体とDB連携のテスト範囲を描きます。

ヒント2

置き換える依存と本物で動かす依存を考えます。

ヒント3

一つの処理の動作と複数要素の連携を別々に説明します。

模範解答と理由

単体テストは小さな処理単位、結合テストは複数コンポーネント間の連携を確認します。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: 単体テストは個別の処理単位の動作を確認する。
  2. 1点: 結合テストはコンポーネント同士の連携を確認する。

満点の正答例: 単体テストは小さな処理単位、結合テストは複数コンポーネント間の連携を確認します。

部分点の判定: 部分正答例:「単体テストは個別の処理単位の動作を確認する」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「単体テストは個別の処理単位の動作を確認する」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「23. 理解度チェック」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

24. 他言語経験者向け補足

Javaのrecordはデータを表現する用途に使え、値の比較のためのequalsも生成されます。ただしrecordの参照先に可変オブジェクトを持つ場合、すべてが自動で不変になるわけではありません。

Mockitoはクラス内部の実装を細かく検証するより、Serviceが依存先とどう協力するかを見るために使うと有効です。

ログ・例外・テストを別々のテクニックとして覚えるのでなく、仕様違反を再現し、原因を限定し、再発を防ぐ一続きの仕事として捉えてください。

この節の独学チェック:24. 他言語経験者向け補足

確認問題: 他言語経験者がJavaのテストで注意する例を一つ挙げてください。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

Java独自の型・例外・等価性の特徴を思い出します。

ヒント2

他言語の同名操作が必ず同じ仕様とは限りません。

ヒント3

BigDecimal・null・equals・検査例外のいずれかで具体例を考えます。

模範解答と理由

BigDecimalのscale、チェック例外、null、equalsによる比較など、Java固有の挙動に注意します。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: BigDecimalのscale、チェック例外、null、equalsによる比較など、Java固有の挙動に注意します。

満点の正答例: BigDecimalのscale、チェック例外、null、equalsによる比較など、Java固有の挙動に注意します。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「BigDecimalのscale、チェック例外、null、equalsによる比較など、Java固有の挙動に注意します」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「24. 他言語経験者向け補足」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

25. 次章へ進む条件

mvn testの全テストが成功し、テスト件数が0ではないこと。税率を一時変更して失敗を再現できたこと。境界値と異常値の理由を説明できること。Mockitoを使ってDBなしの成功・不在・不正IDの3状態を確認できたこと。

ログの出力例を読み、機密情報を記録しない理由を説明できたこと。作業報告を提出できること。どれか未達なら、次章へ進む前に該当節へ戻ります。

学習内容を振り返るための操作確認

この節は、本文の例題や演習が実行できないときに戻るための案内です。最初にファイルの場所と作業中のツールを確認し、コマンドを貼り付ける前に現在のフォルダーを確認してください。

実行する場所と順序

examples/07_practical/pricing の pom.xml があるフォルダーを開き mvn test を実行します。ファイルの一時変更前に正常な結果を保存してください。

成功・失敗の判断

意図的に税率を変更した後の失敗と、戻した後の成功を記録します。テスト件数が0なら成功としてはいけません。

途中で止まったとき

Mavenの依存取得エラーとテストの失敗は別の問題です。前者はネットワークや設定、後者はテストレポートの期待値・実際値を調べます。

作業記録の書き方

  1. 利用環境(OS、Java、必要なツールのバージョン)を記録します。
  2. 実際に操作したフォルダー、実行コマンド、入力内容を記録します。
  3. 期待した結果と実際の結果を別々に書きます。失敗時にはエラーメッセージの全文を保管します。
  4. 修正を加えた場合は変更箇所を記録し、同じ手順で再確認します。
  5. 成功を確認できていなければ「未確認」と記載し、成功と推測して次へ進まないでください。

実際の入力、実行結果、原因の説明、演習の提出物がそろって初めて章の学習を完了とします。

この節の独学チェック:25. 次章へ進む条件

確認問題: 第08章へ進む前に、コード変更時に説明できることは何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

作業差分だけでは変更理由が伝わりません。

ヒント2

どの仕様を、どのテストで確認したか書き出します。

ヒント3

目的・検証・結果を次の担当者へ説明できるか考えます。

模範解答と理由

変更理由、テストで確認した仕様、結果、変更差分を説明できることです。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 変更理由、テストで確認した仕様、結果、変更差分を説明できることです。

満点の正答例: 変更理由、テストで確認した仕様、結果、変更差分を説明できることです。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「変更理由、テストで確認した仕様、結果、変更差分を説明できることです」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「25. 次章へ進む条件」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。