🙆‍♀️

Mockitoとimport static/importの解説

に公開

Mockitoとimport static/importの解説

目次

  1. Mockitoとは
  2. Mockitoの主要機能
  3. mockito-junit-jupiterの特徴
  4. Mockitoの導入方法
  5. モックオブジェクトの作成方法
  6. 振る舞いの定義方法
  7. メソッド呼び出しの検証
  8. import staticとimportの違い
  9. 参考資料

Mockitoとは

Mockitoは、Javaのユニットテストのために開発されたモックフレームワーク(mocking framework)です。テストでモックオブジェクトを直感的に操作できることを目的として開発されています。

キレイでシンプルなAPIでモックを扱うテストコードを記述できること、また記述されたテストコードの可読性が高くわかりやすい検証エラーを生成することがMockitoの特徴です。

Mockitoの主要機能

Mockitoには以下のような主要機能があります:

機能 説明 使用例
mock() モックオブジェクトの作成 UserService mock = mock(UserService.class);
when() 振る舞いの定義 when(mock.findById(1)).thenReturn(user);
verify() メソッド呼び出しの検証 verify(mock).save(user);
any() 引数のマッチング when(mock.find(any())).thenReturn(result);
@Mock アノテーションによるモック定義 @Mock private UserService userService;
@InjectMocks モックの自動注入 @InjectMocks private UserController controller;

mockito-junit-jupiterの特徴

mockito-junit-jupiterは、JUnit 5(Jupiter)とMockitoを連携させるための拡張機能を提供するライブラリです。主な特徴は以下の通りです:

  1. JUnit 5との統合: JUnit 5のExtensionモデルを活用し、テストライフサイクルとMockitoの連携を強化
  2. @ExtendWith(MockitoExtension.class): JUnit 5のテストクラスでMockitoを使用するための拡張機能
  3. 自動初期化: MockitoAnnotationsの初期化を自動的に行う
  4. バージョン互換性: JDK 8, 11, 17, 21など様々なJavaバージョンと互換性がある

Mockitoの導入方法

Mavenの場合

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

<!-- JUnit 5との連携 -->
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>5.14.1</version>
    <scope>test</scope>
</dependency>

Gradleの場合

testImplementation 'org.mockito:mockito-core:5.14.1'
testImplementation 'org.mockito:mockito-junit-jupiter:5.14.1'

モックオブジェクトの作成方法

Mockitoでモックオブジェクトを作成するには、主に2つの方法があります:

1. mock()メソッドを使用する方法

// mock()メソッドを使用してモックオブジェクトを作成
UserService userService = mock(UserService.class);

2. @Mockアノテーションを使用する方法

// @Mockアノテーションを使用
@Mock
private UserService userService;

// テスト対象クラスへの注入
@InjectMocks
private UserController userController;

// JUnit 4の場合
@Before
public void setup() {
    MockitoAnnotations.initMocks(this);
}

// JUnit 5の場合
@ExtendWith(MockitoExtension.class)
class UserControllerTest {
    // 自動的に初期化されるため、別途initMocksは不要
}

振る舞いの定義方法

モックオブジェクトの振る舞いを定義するには、主に2つの方法があります:

1. when().thenReturn()メソッド

// when().thenReturn()を使用して振る舞いを定義
when(userService.findById(1L)).thenReturn(user);
when(userService.findByName("test")).thenThrow(new NotFoundException());

2. doReturn().when()メソッド

// doReturn().when()を使用して振る舞いを定義
doReturn(user).when(userService).findById(1L);
doThrow(new NotFoundException()).when(userService).findByName("test");

doメソッド系は以下の場合に特に有用です:

  • voidメソッドをスタブ化する場合
  • spyオブジェクトを使用する場合
// voidメソッドの場合
doNothing().when(userService).delete(1L);

メソッド呼び出しの検証

モックオブジェクトのメソッド呼び出しを検証するには、verify()メソッドを使用します:

// メソッドが1回呼び出されたことを検証
verify(userService).findById(1L);

// メソッドが特定の回数呼び出されたことを検証
verify(userService, times(2)).findAll();

// メソッドが呼び出されなかったことを検証
verify(userService, never()).delete(any());

// 順序を検証
InOrder inOrder = inOrder(userService, emailService);
inOrder.verify(userService).findById(1L);
inOrder.verify(emailService).sendEmail(any());

import staticとimportの違い

通常のimport

通常のimport文は、パッケージからクラスをインポートすることで、パッケージ修飾なしでクラスを使用できるようにします。

// 通常のimport
import org.mockito.Mockito;

// 使用例
Mockito.mock(UserService.class);

import static

import static文は、クラスからstaticメンバー(メソッドや定数)をインポートすることで、クラス修飾なしでstaticメンバーを使用できるようにします。

// staticメソッドのインポート
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

// 使用例
UserService userService = mock(UserService.class);
when(userService.findById(1L)).thenReturn(user);

主な違い

  1. インポート対象:

    • 通常のimport: クラスをインポート
    • import static: クラスのstaticメンバー(メソッドや定数)をインポート
  2. 使用方法:

    • 通常のimport: クラス名.メソッド名() または クラス名.定数名
    • import static: 直接 メソッド名() または 定数名
  3. インポート構文:

    • 通常のimport: import パッケージ名.クラス名;
    • import static: import static パッケージ名.クラス名.メソッド名; または import static パッケージ名.クラス名.*;

import staticの使用例(Mockitoの場合)

// 個別のstaticメソッドをインポート
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.times;

// 使用例
UserService userService = mock(UserService.class);
when(userService.findById(1L)).thenReturn(user);
verify(userService, times(1)).findById(1L);
// クラスのすべてのstaticメソッドをインポート
import static org.mockito.Mockito.*;

// 使用例
UserService userService = mock(UserService.class);
when(userService.findById(1L)).thenReturn(user);
verify(userService, times(1)).findById(1L);

import staticの注意点

  1. 過剰使用を避ける: 多くのstaticメンバーをインポートすると、名前空間が煩雑になり、コードの可読性が低下する可能性があります。

  2. 名前の衝突: 異なるクラスから同名のstaticメソッドをインポートすると、名前の衝突が発生します。

  3. 適切な使用場面: 1つまたは2つのクラスからstaticメンバーに頻繁にアクセスする必要がある場合に使用するのが適切です。

  4. 個別インポートの推奨: 必要なstaticメンバーだけを個別にインポートする方が、すべてをインポート(import static クラス名.*)するよりも可読性が高くなります。

参考資料

  1. 【保存版】MockitoとJUnitで実現する実践的なJavaテスト入門
  2. Mockitoの使い方 - Qiita
  3. static インポート - Oracle公式ドキュメント
  4. Javaでstaticインポートと通常のインポートの違い - Yahoo!知恵袋

Discussion