Web系開発メモ

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

Java Mockitoでモックを使うテストをする方法

Mockito でモックオブジェクトを作成して、単体テストをする方法を書いていきます。

バージョン

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

目次

  1. 依存関係の追加
  2. テスト対象クラス
  3. 手動でモックを作成
  4. アノテーションでモックを作成
  5. テストの実行
  6. 動作確認用の資源

1. 依存関係の追加

Maven のビルドファイルで、Mockito のライブラリを追加します。

<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-core</artifactId>
  <version>5.1.1</version>
  <scope>test</scope>
</dependency>

Gradle の場合は以下の通りです。

testImplementation 'org.mockito:mockito-core:5.1.1'

2. テスト対象クラス

今回は、以下のサービスクラスをテストします。

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

package org.example.service;

import org.example.model.User;
import org.example.repository.UserRepository;

public class UserService {
  public UserRepository repository;
  public User find(Long id) {
    return repository.find(id);
  }
}

テストでは、リポジトリのモックを作成します。

3. 手動でモックを作成

サービスクラスのテストで、手動でリポジトリのモックを作成する方法は以下の通りです。

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

package org.example.service;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import org.example.model.User;
import org.example.repository.UserRepository;
import org.junit.jupiter.api.Test;

class ManualUserServiceTest {
  private final UserService service = new UserService();

  @Test
  void testFind() {
    // 準備
    UserRepository repository = mock(UserRepository.class);
    when(repository.find(1L)).thenReturn(new User(1L, "鈴木"));
    service.repository = repository;

    // 実行
    User result = service.find(1L);

    // 検証
    assertEquals(1L, result.id);
    assertEquals("鈴木", result.name);
  }
}

mock(...) でモックを作成して、when(...).thenReturn(...) でモックの処理を設定しています。

repository.find(1L) が実行されると、指定した User が返却されます。

4. アノテーションでモックを作成

Mockito のアノテーションを使って、モックを作成する方法は以下の通りです。

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

package org.example.service;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;

import org.example.model.User;
import org.example.repository.UserRepository;
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;

class UserServiceTest {
  // モック
  @Mock UserRepository repository;

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

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

  @Test
  void testFind() {
    // 準備
    when(repository.find(1L)).thenReturn(new User(1L, "鈴木"));

    // 実行
    User result = service.find(1L);

    // 検証
    assertEquals(1L, result.id);
    assertEquals("鈴木", result.name);
  }
}

@Mock で作成したモックを、@InjectMocks のクラスに設定してくれます。

5. テストの実行

IDE でテストクラスを実行するか、プロジェクトのルートディレクトリで以下のコマンドを実行します。

mvn test

6. 動作確認用の資源

6.1. モデル

動作確認で使用したモデルは以下の通りです。

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

package org.example.model;

public class User {
  public Long id;
  public String name;
  public User(Long id, String name) {
    this.id = id;
    this.name = name;
  }
}

6.2. リポジトリ

リポジトリは以下の通りです。

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

package org.example.repository;

import org.example.model.User;

public class UserRepository {
  public User find(Long id) {
    // 省略
  }
}

6.3. ビルドファイル

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>

  <groupId>org.example</groupId>
  <artifactId>test-mockito</artifactId>
  <version>1.0.0</version>
  <packaging>jar</packaging>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
  </properties>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.junit</groupId>
        <artifactId>junit-bom</artifactId>
        <version>5.9.2</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-core</artifactId>
      <version>5.1.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>3.0.0-M8</version>
      </plugin>
    </plugins>
  </build>
</project>