モキートのモックの使用例を示します。
モッキートのモッキングフレームワークは、クラスをモックするさまざまな方法を提供しています。クラスをモックし、その動作をスタブするための異なる手法を見てみましょう。
モッキートのモックメソッド
私たちは、Mockitoクラスのmock()メソッドを使用して、指定されたクラスやインターフェースのモックオブジェクトを作成することができます。これはオブジェクトをモックする最も簡単な方法です。
package com.scdev.mockito.mock;
import java.util.List;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
public class MockitoMockMethodExample {
@SuppressWarnings("unchecked")
@Test
public void test() {
// using Mockito.mock() method
List<String> mockList = mock(List.class);
when(mockList.size()).thenReturn(5);
assertTrue(mockList.size()==5);
}
}
私たちは、オブジェクトをモック化するためにモッキートと一緒にJUnit 5を使用してテストケースを書いています。
モキートの@Mockアノテーション
@Mockのアノテーションを使ってオブジェクトをモックできます。モックオブジェクトを複数の場所で使用する場合に便利です。複数回mock()メソッドを呼び出すことを回避するため、コードがより読みやすくなります。また、エラーが発生した場合に役立つモックオブジェクト名を指定することもできます。@Mockアノテーションを使用する際には、モックオブジェクトを初期化するためにMockitoAnnotations.initMocks(this)を呼び出す必要があります。これはテストの前に実行されるテストフレームワークのセットアップメソッドで行うことができます。
package com.scdev.mockito.mock;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class MockitoMockAnnotationExample {
@Mock
List<String> mockList;
@BeforeEach
public void setup() {
//if we don't call below, we will get NullPointerException
MockitoAnnotations.initMocks(this);
}
@SuppressWarnings("unchecked")
@Test
public void test() {
when(mockList.get(0)).thenReturn("JournalDev");
assertEquals("JournalDev", mockList.get(0));
}
}
モックitoの@InjectMocksアノテーション
もし他のモックオブジェクトにモックオブジェクトを注入したい場合、@InjectMocksアノテーションを使用することができます。@InjectMockは、クラスのモックオブジェクトを作成し、それに@Mockアノテーションでマークされたモックオブジェクトを注入します。
package com.scdev.mockito.mock;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
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 MockitoInjectMockAnnotationExample {
@Mock
List<String> mockList;
//@InjectMock creates an instance of the class and
//injects the mocks that are marked with the annotations @Mock into it.
@InjectMocks
Fruits mockFruits;
@BeforeEach
public void setup() {
//if we don't call below, we will get NullPointerException
MockitoAnnotations.initMocks(this);
}
@SuppressWarnings("unchecked")
@Test
public void test() {
when(mockList.get(0)).thenReturn("Apple");
when(mockList.size()).thenReturn(1);
assertEquals("Apple", mockList.get(0));
assertEquals(1, mockList.size());
//mockFruits names is using mockList, below asserts confirm it
assertEquals("Apple", mockFruits.getNames().get(0));
assertEquals(1, mockFruits.getNames().size());
mockList.add(1, "Mango");
//below will print null because mockList.get(1) is not stubbed
System.out.println(mockList.get(1));
}
}
class Fruits{
private List<String> names;
public List<String> getNames() {
return names;
}
public void setNames(List<String> names) {
this.names = names;
}
}
部分モックに使用するためのMockitoのspy()
特定の振る舞いだけをモックにし、未定義の振る舞いには実際のメソッドを呼び出す場合は、Mockitoのspy()メソッドを使用してスパイオブジェクトを作成できます。
package com.scdev.mockito.mock;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
public class MockitoSpyMethodExample {
@Test
public void test() {
List<String> list = new ArrayList<>();
List<String> spyOnList = spy(list);
when(spyOnList.size()).thenReturn(10);
assertEquals(10, spyOnList.size());
//calling real methods since below methods are not stubbed
spyOnList.add("Pankaj");
spyOnList.add("Meghna");
assertEquals("Pankaj", spyOnList.get(0));
assertEquals("Meghna", spyOnList.get(1));
}
}
モックを作成するためのMockito の`@Spy`アノテーション
オブジェクトを監視するために、@Spyアノテーションを使用することができます。簡単な例を見てみましょう。
package com.scdev.mockito.mock;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
public class MockitoSpyAnnotationExample {
@Spy
Utils mockUtils;
@BeforeEach
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void test() {
when(mockUtils.process(1, 1)).thenReturn(5);
//mocked method
assertEquals(5, mockUtils.process(1, 1));
//real method called since it's not stubbed
assertEquals(20, mockUtils.process(19, 1));
}
}
class Utils{
public int process(int x, int y) {
System.out.println("Input Params = "+x+","+y);
return x+y;
}
}
次のように注釈された@Spyは、モックオブジェクトを初期化するために引数なしのコンストラクタを呼び出そうとします。クラスに引数なしのコンストラクタがない場合、以下のエラーが発生します。
org.mockito.exceptions.base.MockitoException: Unable to initialize @Spy annotated field 'mockUtils'.
Please ensure that the type 'Utils' has a no-arg constructor.
at com.scdev.mockito.mock.MockitoSpyAnnotationExample.setup(MockitoSpyAnnotationExample.java:18)
また、Mockitoでは内部クラス、ローカルクラス、抽象クラス、インターフェースをインスタンス化することができないことに注意してください。そのため、スパイ対象のインスタンスを提供することは常に良いアイデアです。そうしないと、実際のメソッドが呼び出されずに黙って無視される可能性があります。例えば、以下のようにスパイオブジェクトを指定した場合:
@Spy
List<String> spyList;
以下のようにspyオブジェクトを指定すると、add()メソッドやget()メソッドを呼び出しても、実際のメソッドは呼び出されないことに気付くでしょう。しかし、下記のようにspyオブジェクトを指定すれば、すべて正常に動作します。
@Spy
List<String> spyList = new ArrayList<>();
要約
モッキートのモックフレームワークは、さまざまなメソッドやアノテーションを通じて簡単にモックオブジェクトを作成することができます。また、モックオブジェクトを別のモックオブジェクトに注入することもでき、これは非常に便利な機能です。
私たちのGitHubリポジトリから、より多くのMockitoの例を閲覧することができます。