Web系開発メモ

Java, C#, HTML, CSS, JavaScript のことなどを書いてます。

SpringBoot MockitoとJUnitで単体テストをする方法

Spring Boot の Webアプリで、Mockito と JUnit を使って単体テストをする方法を書いていきます。

バージョン

動作確認で使用した製品のバージョンは以下の通りです。

  • Spring Boot 3.0.2
  • Mockito 4.8.1
  • JUnit 5.9.2
  • Java 17

1. ライブラリの追加

Maven のビルドファイルで以下の依存関係を追加します。

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
</dependency>

spring-boot-starter-test を追加すると、JUnit, Mockito, AssertJ などのライブラリが追加されます。

2. テスト対象クラスの作成

テスト対象のサービスクラスを作成します。

src/main/java/org/example/service/TaskService.java

package org.example.service;

import org.example.model.Task;
import org.example.repository.TaskRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class TaskService {
  @Autowired
  TaskRepository repository;

  public Task findById(Long id) {
    return repository.findById(id).get();
  }
}

3. テストクラスの作成

Mockitoでモックを作成して、テストを行うクラスを作成します。

src/test/java/org/example/service/TaskServiceTest.java

package org.example.service;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;

import java.util.Optional;

import org.example.model.Task;
import org.example.repository.TaskRepository;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

public class TaskServiceTest {
  // モック
  @Mock TaskRepository repository;

  // モックを設定するテスト対象クラス
  @InjectMocks TaskService service;

  // モックの設定と解放
  private AutoCloseable closeable;
  @BeforeEach public void openMocks() {
    closeable = MockitoAnnotations.openMocks(this);
  }
  @AfterEach public void releaseMocks() throws Exception {
    closeable.close();
  }

  @Test
  void testFindById() {
    // 準備
    Task expected = new Task();
    expected.setId(1L);
    expected.setTitle("タスク1");
    when(repository.findById(1L)).thenReturn(Optional.of(expected));

    // 実行
    Task result = service.findById(1L);

    // 検証
    assertThat(result.getId()).isEqualTo(1L);
    assertThat(result.getTitle()).isEqualTo("タスク1");
  }
}

4. 関連クラスの作成

サービスクラスが参照するモデルとリポジトリは以下の通りです。

4.1. モデル

src/main/java/org/example/model/Task.java

package org.example.model;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Getter;
import lombok.Setter;

@Entity
@Getter @Setter
public class Task {
  @Id
  @GeneratedValue(strategy= GenerationType.IDENTITY)
  private Long id;

  @Column(nullable = false)
  private String title;
}

4.2. リポジトリ

src/main/java/org/example/repository/TaskRepository.java

package org.example.repository;

import org.example.model.Task;
import org.springframework.data.repository.CrudRepository;

public interface TaskRepository extends CrudRepository<Task, Long> {
}

5. ビルドファイルの作成

Maven のビルドファイルは以下の通りです。

pom.xml

<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 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.0.2</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <groupId>org.example</groupId>
  <artifactId>spring-mockito</artifactId>
  <version>1.0.0</version>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>17</java.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.postgresql</groupId>
      <artifactId>postgresql</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</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-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

6. 動作確認

IDE でテストを実行して、成功することを確認しました。