1. 概要

このクイックチュートリアルでは、MockitoをJUnit5拡張モデルと統合する方法を示します。JUnit 5拡張モデルの詳細については、この記事を参照してください。

最初に、@Mockで注釈が付けられたクラス属性またはメソッドパラメーターのモックオブジェクトを自動的に作成する拡張機能を作成する方法を示します。

次に、JUnit5テストクラスでMockito拡張機能を使用します。

2. Mavenの依存関係

2.1. 必要な依存関係

JUnit 5(jupiter)とmockitoの依存関係をpom.xmlに追加しましょう。

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.8.1</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>2.21.0</version>
    <scope>test</scope>
</dependency>

junit-jupiter-engineはメインのJUnit5ライブラリであり、junit-platform-launcherはMavenプラグインとIDEランチャーで使用されることに注意してください。

2.2. Surefireプラグイン

また、新しいJUnitプラットフォームランチャーを使用してテストクラスを実行するようにMavenSurefireプラグインを構成しましょう。

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.19.1</version>
    <dependencies>
        <dependency>
             <groupId>org.junit.platform</groupId>
             <artifactId>junit-platform-surefire-provider</artifactId>
             <version>1.0.1</version>
         </dependency>
     </dependencies>
</plugin>

2.3. JUnit4IDEの互換性の依存関係

テストケースをJUnit4(ヴィンテージ)互換にするために、JUnit 5をまだサポートしていないIDEの場合は、次の依存関係を含めましょう。

<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-runner</artifactId>
    <version>1.2.0</version>
    <scope>test</scope>
</dependency>
<dependency>
     <groupId>org.junit.vintage</groupId>
     <artifactId>junit-vintage-engine</artifactId>
     <version>5.8.1</version>
     <scope>test</scope>
</dependency>

また、すべてのテストクラスに @RunWith(JUnitPlatform.class)でアノテーションを付けることを検討する必要があります。

junit-jupiter-engine junit-vintage-engine junit-platform-launcher mockito-coreの最新バージョンはMavenCentralからダウンロードできます。

3. Mockitoエクステンション

Mockito は、ライブラリ内のJUnit5拡張機能の実装を提供します— mockito-junit-jupiter

この依存関係をpom.xmlに含めます。

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>2.23.0</version>
    <scope>test</scope>
</dependency>

4. テストクラスの構築

テストクラスを作成し、それにMockito拡張機能をアタッチしてみましょう。

@ExtendWith(MockitoExtension.class)
public class UserServiceUnitTest {

    UserService userService;

... //
}

@Mock アノテーションを使用して、テストクラスのどこでも使用できるインスタンス変数のモックを挿入できます。

@Mock UserRepository userRepository;

また、モックオブジェクトをメソッドパラメータに挿入することもできます。

@BeforeEach
void init(@Mock SettingRepository settingRepository) {
    userService = new DefaultUserService(userRepository, settingRepository, mailClient);
      
    Mockito.lenient().when(settingRepository.getUserMinAge()).thenReturn(10);
        
    when(settingRepository.getUserNameMinLength()).thenReturn(4);
        
    Mockito.lenient()
        .when(userRepository.isUsernameAlreadyExists(any(String.class)))
            .thenReturn(false);
}

ここでMockito.lenient()を使用していることに注意してください。 Mockito は、実行中にテストメソッドの1つによって初期化されたモックが呼び出されない場合、UnsupportedStubbingExceptionをスローします。 モックを初期化するときにこのメソッドを使用することで、この厳密なスタブチェックを回避できます。

テストメソッドのパラメーターにモックオブジェクトを挿入することもできます。

@Test
void givenValidUser_whenSaveUser_thenSucceed(@Mock MailClient mailClient) {
    // Given
    user = new User("Jerry", 12);
    when(userRepository.insert(any(User.class))).then(new Answer<User>() {
        int sequence = 1;
            
        @Override
        public User answer(InvocationOnMock invocation) throws Throwable {
            User user = (User) invocation.getArgument(0);
            user.setId(sequence++);
            return user;
        }
    });

    userService = new DefaultUserService(userRepository, settingRepository, mailClient);

    // When
    User insertedUser = userService.register(user);
        
    // Then
    verify(userRepository).insert(user);
    Assertions.assertNotNull(user.getId());
    verify(mailClient).sendUserRegistrationMail(insertedUser);
}

テストパラメータとして挿入するMailClientモックは、initメソッドで挿入したインスタンスとは異なることに注意してください。

5. 結論

Junit 5は、拡張のための優れたモデルを提供しています。 モック作成ロジックを簡素化する単純なMockito拡張機能をデモンストレーションしました。

この記事で使用されているすべてのコードは、GitHubプロジェクトcom.baeldung.junit5.mockito パッケージに、いくつかの追加の単体テストメソッドとともに含まれています。