Mockito 是一个基于 Java 的模仿框架,与其他测试框架(如 JUnit和 TestNG一起使用,它内部使用 Java Reflection API,并允许创建服务的对象。
马克思 教程
对于Mockito教程,我们将使用JUnit 5并创建一些服务来嘲笑。
Mockito Maven 依赖性
若要在项目中实施基于 Mockito 的测试案例,请将以下依赖性添加到项目的 pom.xml 文件中:
1<dependency>
2 <groupId>org.mockito</groupId>
3 <artifactId>mockito-core</artifactId>
4 <version>2.19.0</version>
5 <scope>test</scope>
6</dependency>
7<dependency>
8 <groupId>org.mockito</groupId>
9 <artifactId>mockito-junit-jupiter</artifactId>
10 <version>2.19.0</version>
11 <scope>test</scope>
12</dependency>
请注意,如果您正在使用任何其他测试框架,如 JUnit 4 或 TestNG,则需要使用mockito-junit-jupiter
,然后删除这种依赖,并只包括mockito-core
依赖。
Mockito Mock 创作
Mockito框架允许我们使用@Mock
注释或mock()
静态方法创建模拟对象。
Mockito Mock() 方法
下面的示例显示了 mock() 方法的使用:
1package com.journaldev.mockito;
2
3import static org.junit.jupiter.api.Assertions.assertEquals;
4import static org.mockito.Mockito.when;
5
6import org.junit.jupiter.api.Test;
7import org.mockito.Mockito;
8
9import com.journaldev.AddService;
10import com.journaldev.CalcService;
11
12public class CalcService1Test {
13
14 @Test
15 void testCalc() {
16 System.out.println("**--- Test testCalc executed ---**");
17
18 AddService addService;
19 CalcService calcService;
20
21 addService = Mockito.mock(AddService.class);
22 calcService = new CalcService(addService);
23
24 int num1 = 11;
25 int num2 = 12;
26 int expected = 23;
27
28 when(addService.add(num1, num2)).thenReturn(expected);
29
30 int actual = calcService.calc(num1, num2);
31
32 assertEquals(expected, actual);
33
34 }
35}
在上面的示例中,我们正在测试CalcService
。Mockito.mock() 方法用于创建AddService
类的模仿对象。
Mockito Mock 评论
下面的示例显示了 @Mock 注释的使用。
1package com.journaldev.mockito;
2
3import static org.junit.jupiter.api.Assertions.assertEquals;
4import static org.mockito.Mockito.when;
5
6import org.junit.jupiter.api.BeforeEach;
7import org.junit.jupiter.api.Test;
8import org.mockito.Mock;
9import org.mockito.MockitoAnnotations;
10
11import com.journaldev.AddService;
12import com.journaldev.CalcService;
13
14public class CalcService2Test {
15
16 CalcService calcService;
17
18 @Mock
19 AddService addService;
20
21 @BeforeEach
22 public void setup() {
23 MockitoAnnotations.initMocks(this);
24 }
25
26 @Test
27 public void testCalc() {
28 System.out.println("**--- Test testCalc executed ---**");
29
30 calcService = new CalcService(addService);
31
32 int num1 = 11;
33 int num2 = 12;
34 int expected = 23;
35
36 when(addService.add(num1, num2)).thenReturn(expected);
37
38 int actual = calcService.calc(num1, num2);
39
40 assertEquals(expected, actual);
41
42 }
43}
请注意,我们需要拨打MockitoAnnotations.initMocks(这);
以初始化用 @Mock、 @Spy、 @Captor 或 @InjectMocks 标注的对象。
Mockito行为验证
要将行为添加到模仿类中,则使用when()
和thenReturn()
函数,这意味着当模仿对象(addService)被调用以添加(num1, num2)参数的方法时,它会返回预期变量中存储的值。
1public class CalcService {
2
3 private AddService addService;
4
5 public CalcService(AddService addService) {
6 this.addService = addService;
7 }
8
9 public int calc(int num1, int num2) {
10 System.out.println("**--- CalcService calc executed ---**");
11 return addService.add(num1, num2);
12 }
13
14}
CalcService 依赖于 AddService 类. 它使用 AddService 类的添加方法来执行其操作. 由于我们只想对 CalcService 类进行单元测试,我们必须嘲笑 AddService 实例。
1public interface AddService {
2 public int add(int num1, int num2);
3}
1public class AddServiceImpl implements AddService {
2 @Override
3 public int add(int num1, int num2) {
4 System.out.println("**--- AddServiceImpl add executed ---**");
5 return num1 + num2;
6 }
7}
Mockito 查看互动
Mockito 框架会跟踪所有方法调用和它们的参数到模特对象。 Mockito 对模特对象的verify()
方法会验证以某些参数调用一种方法。我们还可以指定调用逻辑的数量,例如确切的次数,至少确定的次数,少于指定的次数等。我们可以使用VerificationModeFactory
用于调用次数逻辑。 Mockito verify() 方法会检查以正确的参数调用一种方法。
1package com.journaldev.mockito;
2
3import static org.mockito.Mockito.verify;
4
5import java.util.List;
6
7import org.junit.jupiter.api.Test;
8import org.mockito.Mockito;
9import org.mockito.internal.verification.VerificationModeFactory;
10
11public class VerifyInteractionTest {
12 @Test
13 public void testMethod() {
14 @SuppressWarnings("unchecked")
15 List<String> mockedList = Mockito.mock(List.class);
16
17 mockedList.add("first-element");
18 mockedList.add("second-element");
19 mockedList.add("third-element");
20 mockedList.add("third-element");
21 mockedList.clear();
22
23 verify(mockedList).add("first-element");
24 verify(mockedList).add("second-element");
25 verify(mockedList, VerificationModeFactory.times(2)).add("third-element");
26
27 verify(mockedList).clear();
28 }
29
30}
Mockito Stub 混凝土类
使用 when() - 然后Return() 函数,我们可以建立一个混凝土 / 实现类和一个集合的单个元素。
1package com.journaldev.mockito;
2
3import static org.mockito.Mockito.mock;
4import static org.mockito.Mockito.when;
5
6import java.util.ArrayList;
7
8import org.junit.jupiter.api.Test;
9import static org.junit.jupiter.api.Assertions.assertEquals;
10
11public class MockSingleElementTest {
12 @SuppressWarnings("unchecked")
13 @Test
14 public void testMethod() {
15 ArrayList mockedList = mock(ArrayList.class);
16
17 when(mockedList.get(0)).thenReturn("first-element");
18
19 System.out.println(mockedList.get(0));
20 assertEquals("first-element", mockedList.get(0));
21
22 // "null" gets printed as get(1) is not stubbed
23 System.out.println(mockedList.get(1));
24 }
25
26}
马克思间谍
当您调用间谍对象的方法时,将调用真实的方法,除非已定义了预先定义的行为。
1package com.journaldev.mockito;
2
3import static org.junit.jupiter.api.Assertions.assertEquals;
4import static org.mockito.Mockito.spy;
5import static org.mockito.Mockito.when;
6
7import java.util.ArrayList;
8import java.util.List;
9
10import org.junit.jupiter.api.Test;
11
12public class MockitoSpyTest {
13
14 @Test
15 public void testMethod() {
16 List<String> list = new ArrayList<>();
17 List<String> listSpy = spy(list);
18
19 listSpy.add("first-element");
20 System.out.println(listSpy.get(0));
21
22 assertEquals("first-element", listSpy.get(0));
23 when(listSpy.get(0)).thenReturn("second-element");
24 System.out.println(listSpy.get(0));
25 assertEquals("second-element", listSpy.get(0));
26 }
27
28}
结论
Mockito 是用于 Java 单元测试的流行的模仿框架,我们可以使用 Mockito 轻松地模仿依赖性。Mockito 编码风格流畅,类似于 JUnit 和 TestNG 框架,因此其学习曲线非常小。
您可以从我们的 GitHub 存储库下载完整的项目代码。