JUnit

Spring Boot 2.7を利用したJavaアプリケーションでJUnit4とJUnit5のテストを実行してみた

Spring Boot 2.7を利用したJavaアプリケーションでJUnitを用いると、通常はJUnit5で動作するが、JUnit4とJUnit5の両方で動作するような設定も行うことができる。

今回は、Spring Boot 2.7を利用したJavaアプリケーションのJUnitによるテストコードを、JUnit4とJUnit5の両方で動作できるようにし、更にMockitoを利用してみたので、そのサンプルプログラムを共有する。

前提条件

下記記事の実装が完了していること。

JunitのMockitoを利用してモック化したオブジェクトの引数と呼出回数を取得してみたJUnitのテストを行う際、Mock化したメソッドの戻り値がvoid型で、Mock化したメソッドが呼ばれたかどうかわからない場合がある。...

サンプルプログラムの作成

前提条件の記事のプログラムを、ビルドツールmavenを利用しSTS上に配置後、JUnitを用いたテストコードを作成する。

作成したサンプルプログラムの構成は、以下の通り。なお、下記の赤枠は、前提条件のプログラムから変更したプログラムである。
サンプルプログラムの構成

pom.xmlの内容は以下の通りで、spring-boot-starter-testを使う設定を、JUnit4, JUnit5の両方で使えるよう、変更している。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.18</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>
  <groupId>com.example.demo</groupId>
  <artifactId>demoSpringTest</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  <name>demoSpringTest</name>
  <description>Demo Web Project for Spring Boot on Azure</description>
  <properties>
    <java.version>1.8</java.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <scope>provided</scope>
    </dependency>
    <!-- バリデーションチェックを行うための設定 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
    <!-- lombokを利用するための設定 -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <scope>provided</scope>
    </dependency>
    <!-- SQL Serverを利用するための設定 -->
    <!-- ドライバーが SSL (Secure Sockets Layer) 暗号化による
       SQL Server への安全な接続を確立できませんでした。というエラー
       (SQLServerException)を回避するため、SQL Serverに
                接続するためのJDBCドライバのバージョンを変更 -->
    <dependency>
      <groupId>com.microsoft.sqlserver</groupId>
      <artifactId>mssql-jdbc</artifactId>
      <version>9.4.1.jre8</version>
    </dependency>
    <!-- MyBatisを利用するための設定 -->
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>2.3.2</version>
    </dependency>
    <!-- テスト用の設定 start -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
      <!-- Spring Boot 2.7の場合、デフォルトでJUnit5を利用するための設定を除外 -->
      <exclusions>
        <exclusion>
          <groupId>org.junit.jupiter</groupId>
          <artifactId>junit-jupiter</artifactId>
        </exclusion>
        <exclusion>
          <groupId>org.junit.vintage</groupId>
          <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
        <exclusion>
          <groupId>org.mockito</groupId>
          <artifactId>mockito-junit-jupiter</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <!-- JUnit5を利用するための設定 -->
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-engine</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.junit.platform</groupId>
      <artifactId>junit-platform-launcher</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.junit.vintage</groupId>
      <artifactId>junit-vintage-engine</artifactId>
      <scope>test</scope>
    </dependency>
    <!-- JUnit5でMockitoを利用するための設定 -->
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-core</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-junit-jupiter</artifactId>
      <scope>test</scope>
    </dependency>
    <!-- JUnit4を利用するための設定(Mockitoも使える)  -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <scope>test</scope>
    </dependency>
    <!-- テスト用の設定 end -->
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

また、JUnit4でMockitoを利用した際のソースコードは、以下の通り。

package com.example.demo;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.time.LocalDate;
import java.util.List;

import static org.mockito.Mockito.when;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.any;

// JUnit4のアサーションを指定
import static org.junit.Assert.assertEquals;

@RunWith(JUnit4.class)  // JUnit4で実行
public class DemoServiceImplTestJunit4 {

  /**
   * テスト対象のクラス
   * (今回はSpring Bootを利用しないため、Serviceではなく
   *  ServiceImplを対象クラスに指定している)
   */
  @InjectMocks
  private DemoServiceImpl demoServiceImpl;

  /**
   * テスト対象のクラス内で呼ばれるクラスのMockオブジェクト
   */
  @Mock
  private UserDataMapper mapper;
  
  /**
   * 初期化したMockオブジェクトを保持するクラス
   */
  private AutoCloseable closeable;

  /**
   * 前処理(各テストケースを実行する前に行われる処理)
   */
  @Before  // JUnit4のアノテーション
  public void init() {
    /* @Mockアノテーションのモックオブジェクトを初期化
     * これを実行しないと@Mockアノテーション、@InjectMocksを付与した
     * Mockオブジェクトが利用できない
     * MockitoAnnotations.initMocksメソッドは非推奨となったため
     * 代わりにopenMocksメソッドを利用 */
    closeable = MockitoAnnotations.openMocks(this);

    // Mockの設定
    // mapper.findMaxId()メソッドを実行した際の戻り値をここで設定
    when(mapper.findMaxId()).thenReturn(2L);
  }

  /**
   * DemoServiceImplクラスのcreateOrUpdateForAddメソッド(追加時)の確認
   */
  @Test  // JUnit4のアノテーション
  public void testCreateOrUpdateForAdd(){
    // 追加処理を行う場合の、テスト対象メソッドの引数を生成
    DemoForm demoFormAdd = makeDemoForm(null, "テスト プリン3"
        , LocalDate.of(2014, 4, 20), SexEnum.MAN);

    // テスト対象メソッドの実行
    demoServiceImpl.createOrUpdate(demoFormAdd);
    System.out.println("*** demoServiceImpl.createOrUpdateForAdd"
        + "(DemoForm(追加用))の実行結果 ***");

    // テスト対象メソッドを実行した結果、mapper.findMaxId()が1回呼ばれたことを確認
    verify(mapper, times(1)).findMaxId();
    System.out.println("mapper.findMaxId()は1回呼ばれました");

    // テスト対象メソッドを実行した結果、mapper.create(UserData)が1回呼ばれたことを確認
    ArgumentCaptor<UserData> userDataCaptor
        = ArgumentCaptor.forClass(UserData.class);
    verify(mapper, times(1))
        .create(userDataCaptor.capture());
    System.out.println("mapper.create(UserData)は1回呼ばれました");

    // mapper.create(UserData)を呼び出した際の引数が想定通りであることを確認
    List<UserData> listUserData = userDataCaptor.getAllValues();
    assertEquals(1, listUserData.size());
    UserData expectUserData = makeUserData(3L, "テスト プリン3"
        , LocalDate.of(2014, 4, 20), SexEnum.MAN);
    assertEquals(expectUserData.toString(), listUserData.get(0).toString());
    System.out.println("mapper.create(UserData)の引数 : "
        + listUserData.get(0).toString());

    // テスト対象メソッドを実行した結果、mapper.update(UserData)は呼ばれないことを確認
    // any()は任意の引数を表す
    verify(mapper, times(0)).update(any());
    System.out.println("mapper.update(UserData)は呼ばれませんでした");
    System.out.println();
  }

  /**
   * DemoServiceImplクラスのcreateOrUpdateForAddメソッド(更新時)の確認
   */
  @Test  // JUnit4のアノテーション
  public void testCreateOrUpdateForUpdate(){
    // 更新処理を行う場合の、テスト対象メソッドの引数を生成
    DemoForm demoFormUpd = makeDemoForm(2L, "テスト プリン2"
        , LocalDate.of(2013, 3, 19), SexEnum.WOMAN);

    // テスト対象メソッドの実行
    demoServiceImpl.createOrUpdate(demoFormUpd);
    System.out.println("*** demoServiceImpl.createOrUpdateForAdd"
        + "(DemoForm(更新用))の実行結果 ***");

    // テスト対象メソッドを実行した結果、mapper.findMaxId()が呼ばれないことを確認
    verify(mapper, times(0)).findMaxId();
    System.out.println("mapper.findMaxId()は呼ばれませんでした");

    // テスト対象メソッドを実行した結果、mapper.create(UserData)が呼ばれないことを確認
    verify(mapper, times(0)).create(any());
    System.out.println("mapper.create(UserData)は呼ばれませんでした");

    // テスト対象メソッドを実行した結果、mapper.update(UserData)が1回呼ばれたことを確認
    ArgumentCaptor<UserData> userDataCaptor
        = ArgumentCaptor.forClass(UserData.class);
    verify(mapper, times(1))
        .update(userDataCaptor.capture());
    System.out.println("mapper.update(UserData)は1回呼ばれました");

    // mapper.update(UserData)を呼び出した際の引数が想定通りであることを確認
    List<UserData> listUserData = userDataCaptor.getAllValues();
    assertEquals(1, listUserData.size());
    UserData expectUserData = makeUserData(2L, "テスト プリン2"
        , LocalDate.of(2013, 3, 19), SexEnum.WOMAN);
    assertEquals(expectUserData.toString(), listUserData.get(0).toString());
    System.out.println("mapper.update(UserData)の引数 : "
        + listUserData.get(0).toString());
    System.out.println();
  }
  
  /**
   * 後処理(各テストケースを実行した前に行われる処理)
   * @throws Exception 何らかの例外
   */
  @After  // JUnit4のアノテーション
  public void terminate() throws Exception {
    // Mockオブジェクトのリソースを解放
    closeable.close();
  }

  /**
   * ユーザーデータを生成する
   * @param id ID
   * @param name 名前
   * @param birthDay 生年月日
   * @param sexEnum 性別Enum
   * @return ユーザーデータ
   */
  private UserData makeUserData(Long id, String name, LocalDate birthDay, SexEnum sexEnum){
    UserData userData = new UserData();
    if(id != null){
      userData.setId(id);
    }
    userData.setName(name);
    if(birthDay != null){
      userData.setBirthY(birthDay.getYear());
      userData.setBirthM(birthDay.getMonthValue());
      userData.setBirthD(birthDay.getDayOfMonth());
    }
    if(sexEnum != null){
      userData.setSex(sexEnum.getSex());
      userData.setSex_value(sexEnum.getSex_value());
    }
    return userData;
  }

  /**
   * Demoフォームオブジェクトを生成する
   * @param id ID
   * @param name 名前
   * @param birthDay 生年月日
   * @param sexEnum 性別Enum
   * @return Demoフォームオブジェクト
   */
  private DemoForm makeDemoForm(Long id, String name, LocalDate birthDay, SexEnum sexEnum){
    DemoForm demoForm = new DemoForm();
    if(id != null){
      demoForm.setId(String.valueOf(id));
    }
    demoForm.setName(name);
    if(birthDay != null){
      demoForm.setBirthYear(String.valueOf(birthDay.getYear()));
      demoForm.setBirthMonth(String.valueOf(birthDay.getMonthValue()));
      demoForm.setBirthDay(String.valueOf(birthDay.getDayOfMonth()));
    }
    if(sexEnum != null){
      demoForm.setSex(sexEnum.getSex());
      demoForm.setSex_value(sexEnum.getSex_value());
    }
    return demoForm;
  }
}

さらに、JUnit5でMockitoを利用した際のソースコードは、以下の通り。

package com.example.demo;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;

import java.time.LocalDate;
import java.util.List;

import static org.mockito.Mockito.when;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.any;

// JUnit5のアサーションを指定
import static org.junit.jupiter.api.Assertions.assertEquals;

@ExtendWith(MockitoExtension.class)  // JUnit5で実行
public class DemoServiceImplTestJunit5 {

  /**
   * テスト対象のクラス
   * (今回はSpring Bootを利用しないため、Serviceではなく
   *  ServiceImplを対象クラスに指定している)
   */
  @InjectMocks
  private DemoServiceImpl demoServiceImpl;

  /**
   * テスト対象のクラス内で呼ばれるクラスのMockオブジェクト
   */
  /* JUnit5でorg.mockito.exceptions.misusing.UnnecessaryStubbingException
   * 例外が発生するのを抑止するため、@Mockアノテーションの属性にlenient=true を指定  */
  @Mock(lenient = true)
  private UserDataMapper mapper;
  
  /**
   * 初期化したMockオブジェクトを保持するクラス
   */
  private AutoCloseable closeable;

  /**
   * 前処理(各テストケースを実行する前に行われる処理)
   */
  @BeforeEach  // JUnit5のアノテーション
  public void init() {
    /* @Mockアノテーションのモックオブジェクトを初期化
     * これを実行しないと@Mockアノテーション、@InjectMocksを付与した
     * Mockオブジェクトが利用できない
     * MockitoAnnotations.initMocksメソッドは非推奨となったため
     * 代わりにopenMocksメソッドを利用 */
    closeable = MockitoAnnotations.openMocks(this);

    // Mockの設定
    // mapper.findMaxId()メソッドを実行した際の戻り値をここで設定
  	when(mapper.findMaxId()).thenReturn(2L);
  }

  /**
   * DemoServiceImplクラスのcreateOrUpdateForAddメソッド(追加時)の確認
   */
  @Test  // JUnit5のアノテーション
  public void testCreateOrUpdateForAdd(){
    // 追加処理を行う場合の、テスト対象メソッドの引数を生成
    DemoForm demoFormAdd = makeDemoForm(null, "テスト プリン3"
        , LocalDate.of(2014, 4, 20), SexEnum.MAN);

    // テスト対象メソッドの実行
    demoServiceImpl.createOrUpdate(demoFormAdd);
    System.out.println("*** demoServiceImpl.createOrUpdateForAdd"
        + "(DemoForm(追加用))の実行結果 ***");

    // テスト対象メソッドを実行した結果、mapper.findMaxId()が1回呼ばれたことを確認
    verify(mapper, times(1)).findMaxId();
    System.out.println("mapper.findMaxId()は1回呼ばれました");

    // テスト対象メソッドを実行した結果、mapper.create(UserData)が1回呼ばれたことを確認
    ArgumentCaptor<UserData> userDataCaptor
        = ArgumentCaptor.forClass(UserData.class);
    verify(mapper, times(1))
        .create(userDataCaptor.capture());
    System.out.println("mapper.create(UserData)は1回呼ばれました");

    // mapper.create(UserData)を呼び出した際の引数が想定通りであることを確認
    List<UserData> listUserData = userDataCaptor.getAllValues();
    assertEquals(1, listUserData.size());
    UserData expectUserData = makeUserData(3L, "テスト プリン3"
        , LocalDate.of(2014, 4, 20), SexEnum.MAN);
    assertEquals(expectUserData.toString(), listUserData.get(0).toString());
    System.out.println("mapper.create(UserData)の引数 : "
        + listUserData.get(0).toString());

    // テスト対象メソッドを実行した結果、mapper.update(UserData)は呼ばれないことを確認
    // any()は任意の引数を表す
    verify(mapper, times(0)).update(any());
    System.out.println("mapper.update(UserData)は呼ばれませんでした");
    System.out.println();
  }

  /**
   * DemoServiceImplクラスのcreateOrUpdateForAddメソッド(更新時)の確認
   */
  @Test  // JUnit5のアノテーション
  public void testCreateOrUpdateForUpdate(){
    // 更新処理を行う場合の、テスト対象メソッドの引数を生成
    DemoForm demoFormUpd = makeDemoForm(2L, "テスト プリン2"
        , LocalDate.of(2013, 3, 19), SexEnum.WOMAN);

    // テスト対象メソッドの実行
    demoServiceImpl.createOrUpdate(demoFormUpd);
    System.out.println("*** demoServiceImpl.createOrUpdateForAdd"
        + "(DemoForm(更新用))の実行結果 ***");

    // テスト対象メソッドを実行した結果、mapper.findMaxId()が呼ばれないことを確認
    verify(mapper, times(0)).findMaxId();
    System.out.println("mapper.findMaxId()は呼ばれませんでした");

    // テスト対象メソッドを実行した結果、mapper.create(UserData)が呼ばれないことを確認
    verify(mapper, times(0)).create(any());
    System.out.println("mapper.create(UserData)は呼ばれませんでした");

    // テスト対象メソッドを実行した結果、mapper.update(UserData)が1回呼ばれたことを確認
    ArgumentCaptor<UserData> userDataCaptor
        = ArgumentCaptor.forClass(UserData.class);
    verify(mapper, times(1))
        .update(userDataCaptor.capture());
    System.out.println("mapper.update(UserData)は1回呼ばれました");

    // mapper.update(UserData)を呼び出した際の引数が想定通りであることを確認
    List<UserData> listUserData = userDataCaptor.getAllValues();
    assertEquals(1, listUserData.size());
    UserData expectUserData = makeUserData(2L, "テスト プリン2"
        , LocalDate.of(2013, 3, 19), SexEnum.WOMAN);
    assertEquals(expectUserData.toString(), listUserData.get(0).toString());
    System.out.println("mapper.update(UserData)の引数 : "
        + listUserData.get(0).toString());
    System.out.println();
  }
  
  /**
   * 後処理(各テストケースを実行した前に行われる処理)
   * @throws Exception 何らかの例外
   */
  @AfterEach  // JUnit5のアノテーション
  public void terminate() throws Exception {
    // Mockオブジェクトのリソースを解放
    closeable.close();
  }

  /**
   * ユーザーデータを生成する
   * @param id ID
   * @param name 名前
   * @param birthDay 生年月日
   * @param sexEnum 性別Enum
   * @return ユーザーデータ
   */
  private UserData makeUserData(Long id, String name, LocalDate birthDay, SexEnum sexEnum){
    UserData userData = new UserData();
    if(id != null){
      userData.setId(id);
    }
    userData.setName(name);
    if(birthDay != null){
      userData.setBirthY(birthDay.getYear());
      userData.setBirthM(birthDay.getMonthValue());
      userData.setBirthD(birthDay.getDayOfMonth());
    }
    if(sexEnum != null){
      userData.setSex(sexEnum.getSex());
      userData.setSex_value(sexEnum.getSex_value());
    }
    return userData;
  }

  /**
   * Demoフォームオブジェクトを生成する
   * @param id ID
   * @param name 名前
   * @param birthDay 生年月日
   * @param sexEnum 性別Enum
   * @return Demoフォームオブジェクト
   */
  private DemoForm makeDemoForm(Long id, String name, LocalDate birthDay, SexEnum sexEnum){
    DemoForm demoForm = new DemoForm();
    if(id != null){
      demoForm.setId(String.valueOf(id));
    }
    demoForm.setName(name);
    if(birthDay != null){
      demoForm.setBirthYear(String.valueOf(birthDay.getYear()));
      demoForm.setBirthMonth(String.valueOf(birthDay.getMonthValue()));
      demoForm.setBirthDay(String.valueOf(birthDay.getDayOfMonth()));
    }
    if(sexEnum != null){
      demoForm.setSex(sexEnum.getSex());
      demoForm.setSex_value(sexEnum.getSex_value());
    }
    return demoForm;
  }
}

その他のソースコードについては、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/spring-boot-27-junit4-junit5/demoSpringTest/



ウズウズカレッジJavaコースはわかりやすい動画教材と充実した就業サポートで優良企業を目指せるプログラミングスクールだったJavaは、世界中で広く使われていて、現在の需要が高く将来性もある開発言語になります。 https://www.acrovision....

サンプルプログラムの実行結果

サンプルプログラムの実行結果は、以下の通り。

1)「DemoServiceImplTestJunit4.java」を実行した結果は、以下の通りで、正常に実行できている。
サンプルプログラムの実行結果_1

2)「DemoServiceImplTestJunit5.java」を実行した結果は、以下の通りで、正常に実行できている。
サンプルプログラムの実行結果_2



Androidロックを解除する裏ワザ「4uKey for Android」をご紹介Android端末では、以下の画像のような画面ロックパスワードを設定することができますが、このパスワードを忘れてしまうと、Android...

サンプルプログラムのpom.xml(テスト用の設定)の完成経緯

サンプルプログラムのpom.xml(テスト用の設定)が完成するまでの経緯は、以下の通り。

1) pom.xmlの「テスト用の設定」を、以下のように修正する。

<!-- テスト用の設定 start -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<!-- テスト用の設定 end -->

2) Spring Boot 2.7の場合、デフォルトでJUnit5を利用する設定になっているため、以下のように、JUnit4のテストクラスでコンパイルエラーが発生していることが確認できる。
経緯_2

3) pom.xmlの「テスト用の設定」を、以下のように修正する。

<!-- テスト用の設定 start -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<!-- JUnit4を利用するための設定(Mockitoも使える)  -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</scope>
</dependency>
<!-- テスト用の設定 end -->

4) 以下のように、JUnit4のテストクラスのコンパイルエラーが解消されたことが確認できる。
経緯_4

5) ただし、実行すると、以下のように「テスト・ランナー ‘Junit 5’のテストが見つかりません。」と表示される。
経緯_5_1

経緯_5_2

6) pom.xmlの「テスト用の設定」を、以下のように修正する。

<!-- テスト用の設定 start -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <!-- Spring Boot 2.7の場合、デフォルトでJUnit5を利用するための設定を除外 -->
    <exclusions>
        <exclusion>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-junit-jupiter</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- JUnit4を利用するための設定(Mockitoも使える)  -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</scope>
</dependency>
<!-- テスト用の設定 end -->

7) 以下のように、次はJUnit5のテストクラスでコンパイルエラーが発生することが確認できる。
経緯_7

8) pom.xmlの「テスト用の設定」を、以下のように修正する。

<!-- テスト用の設定 start -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <!-- Spring Boot 2.7の場合、デフォルトでJUnit5を利用するための設定を除外 -->
    <exclusions>
        <exclusion>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-junit-jupiter</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- JUnit5を利用するための設定 -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-launcher</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <scope>test</scope>
</dependency>
<!-- JUnit4を利用するための設定(Mockitoも使える)  -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</scope>
</dependency>
<!-- テスト用の設定 end -->

9) 以下のように、JUnit5のテストクラスでコンパイルエラーがまだ少し残っていることが確認できる。
経緯_9

10) pom.xmlの「テスト用の設定」を、以下のように、サンプルプログラムと同じ状態に修正する。

<!-- テスト用の設定 start -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <!-- Spring Boot 2.7の場合、デフォルトでJUnit5を利用するための設定を除外 -->
    <exclusions>
        <exclusion>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-junit-jupiter</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- JUnit5を利用するための設定 -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-launcher</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <scope>test</scope>
</dependency>
<!-- JUnit5でMockitoを利用するための設定 -->
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <scope>test</scope>
</dependency>
<!-- JUnit4を利用するための設定(Mockitoも使える)  -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</scope>
</dependency>
<!-- テスト用の設定 end -->

11) 以下のように、JUnit5のテストクラスのコンパイルエラーが無くなることが確認できる。
経緯_11

このときの実行結果は、「サンプルプログラムの実行結果」に記載の通りとなる。

要点まとめ

  • Spring Boot 2.7を利用したJavaアプリケーションでJUnitを用いると、通常はJUnit5で動作するが、設定次第で、JUnit4とJUnit5の両方で動作した上で、Mockitoも利用できる。