ユニットテスト
ユニットテストとは
設計通りに単体で正しく動くか検証するテストのことです。 画面を使用する手動(打鍵)テストとの大きな違いは、画面やDBなどの外部環境に依存しない点です。
たとえ画面の構築が終わっていなかったり画面側でエラーが出たりする状態でも、
バックエンドのクラス単体で動作をテストできるため、障害が発生した際も「画面の問題」と「ロジックの問題」を明確に切り分けることができます。 ユニットテストの圧倒的に優れている点は『再現性の高さ』と『デグレ(先祖返り・退行)確認の容易さ』です。
画面打鍵でのテストの場合、例えば結合テストでバグが見つかりプログラムを修正したあと再度テストしようとすると、
DBのデータなどを当時の状態へ完璧に戻す必要があります。
これは実務において非常に困難な場合が多く、データが少し違うだけで「データが原因で結果が変わったのでは?」と疑心暗鬼になりがちです。 一方でユニットテストは、テストケースやデータ(状態)がすでにソースコードとして定義されているため、常に全く同じ環境・条件で一瞬でテストを再実行できます。
問題点としては、クラスの作り次第ではユニットテストが『やりにくい』事もあります。
※その場合は打鍵テストに切り替える場合が多いです。
俗に『良いクラスの作りはユニットテストがしやすい事』と言われますが、それを意識したクラス構築を心がけましょう。
pom.xml
<!-- JUnit 5 (Jupiter API & Engine Aggregator) -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.2</version>
<scope>test</scope>
</dependency>
<!-- Mockito Core (モックオブジェクト作成用) -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
<!-- Mockito JUnit 5 統合用 (@ExtendWith(MockitoExtension.class) を使用する場合) -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
内容の通り『JUnit 5』を使用します。
2017年のリリースとなり、現在(2025年)は『JUnit 6』もリリースされています。 しかし「Java 17以降」でしか動作しないため、今回は『5』での説明とします。
また『JUnit 5』のコードは、基本的に『JUnit 6』でも動作しますので内容的には問題はありません。
テストクラス作成
今回は以下の様なサンプルクラスを作成します。
package service;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import utility.DateUtil;
import dto.SampleDto;
import entity.User;
import jakarta.enterprise.context.Dependent;
import jakarta.inject.Inject;
import logic.SampleLogic;
@Dependent
public class SampleService {
private static final Logger logger = LoggerFactory.getLogger(SampleService.class);
@Inject
private SampleDto dto;
@Inject
public SampleLogic appLogic;
public String chkUserInfo(String name) {
logger.info("------------- SampleService.chkUserInfo ---------------");
dto.setName(name);
String ymd = DateUtil.getNowToString();
List<User> list = appLogic.selectUserInfo(dto, ymd);
if (list != null && list.size() > 0) {
for (User ent : list) {
if (ent.getName().equals(name)) {
return "ユーザー『" + name + "』は存在します。";
}
}
return "ユーザー『" + name + "』はいません。";
}
return "ユーザーは誰もいません。";
}
}
出来るだけエラー状態(赤下線)は、よろしくないので少し説明します。
プロパティ『private String name;』のみ定義が必要です。
静的メソッドとして以下内容としています。
LocalDate date = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
return date.format(formatter);
}
『User』クラスは、パッケージ『entity』にプロパティ『private String name;』を設定します。
『SampleLogic』クラスは、パッケージ『logic』にメソッド『public List<User> selectUserInfo(SampleDto dto, String ymd)』を作成します。
※返却は「null」で良いです
[新規] > [その他] > ダイアログがPOPします。
[Java] > [JUnit] > [JUnit テスト・ケース] > [次へ] ラジオボタンが「新規 JUnit Jupiter テスト」となっている事
ソース・フォルダーが「jakaruta-pj/src/test/java」になっている事を確認し『完了』を押下します。
すると以下の様なテストクラスが生成されます。
package service;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class SampleServiceTest {
@Test
void test() {
fail("まだ実装されていません");
}
}
テストの実行
※『@Test』を付与したメソッドがテストメソッドとなり、複数作成する事も可能です
String foo = "ふ~";
assertNotEquals(hoge, foo);
[実行(R)]を選択すると以下の様なメニューとなりますので『2 JUnitテスト』を選択します。
2 JUnitテスト
3 ...

緑はテスト成功を意味します! 試しにテストコードを以下の様に修正して実施してみてください。
⇒
assertEquals(hoge, foo);
当然これはテスト失敗を意味します。
org.opentest4j.AssertionFailedError: expected: <ほげ> but was: <ふ~>
at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
at org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:197)
at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:182)
at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:177)
at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:1145)
at service.SampleServiceTest.test(SampleServiceTest.java:13)
at java.base/java.lang.reflect.Method.invoke(Method.java:569)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
明確に『テストは[ほげ]を期待したけど[ふ~]だったよ』と言っています。
そして『SampleServiceTest.java:13』とテストした行数も教えて貰っています。
ユニットテストのライフサイクル
@AfterAll すべてのテストの実行後の処理
@BeforeEach 各テストの実行前の処理
@AfterEach 各テストの実行後の処理
またこのメソッドは『static』でなければいけません。
つまり複数のテストメソッドがあれば、都度実行されます。
またこのメソッドは通常(staticではない)のメソッドで構いません。
package service;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
class SampleServiceTest {
private static String foo;
private String hoge;
@BeforeAll
static void beforeAll() {
foo = "ふ~";
}
@BeforeEach
void setUp(TestInfo testInfo) {
hoge = "ほげ";
// 実行中のテストメソッド名を取得
String methodName = testInfo.getTestMethod().get().getName();
if (methodName.equals("test_02")) {
hoge = "ふ~";
}
}
@Test
void test_01() {
assertEquals(hoge, foo);
}
@Test
void test_02() {
assertEquals(hoge, foo);
}
}
しかし『JUnit』タブの各テストアイコンを見てください。
メソッド名《test_02》だけ成功しているのが確認できるハズです。
これは『BeforeEach』処理で、メソッド名《test_02》の場合変数『hoge』の値を変更しているためです。 今回はテストソースの中で値を定義しましたが、実際は当然開発ソースの内容をテストします。
本章では『JUnit 5』の基本となり、テストソースの自動生成からテスト実行方法までとなります。
その場合は『beans.xml』の内容を修正します。
bean-discovery-mode="all">
</beans>
⇒
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
bean-discovery-mode="annotated">
</beans>
『beans.xml』の「bean-discovery-mode」とは、CDI(Contexts and Dependency Injection)がアプリケーション内のクラスをどれだけ自動的にインジェクション対象として認識するかを決める設定です。
《all》は当然全てとなりますが《annotated》は、明示的にCDI用の注釈が付いたクラスのみが対象となります。
これは今まで省略(または忘れていた)注釈を《all》が補完していた場合に発生します。
また《all》の設定でなぜ『TestInfo』がエラーの原因となったかと言うと『TestInfo』をCDIで解決しようとした結果となります。
つまり、CDI解決しようとしたが『TestInfo』には具体的な実装クラスが存在しないためエラーとなるのです。





『test』フォルダが無い場合は、以下のパスを作成します。
次にプロジェクトを右クリックし『ビルド・パス(B)』>『ビルドパスの構成(C)』を選択します。src/test/java
『ソース』タブに『{プロジェクト名}/src/test/java』が存在するか確認してください。
存在しない場合は『フォルダーの追加』ボタンを押下し追加して下さい。