原文: https://howtodoinjava.com/mockito/junit-mockito-example/

在本 mockito 教程中,学习了 Mockito 框架的基础知识,如何编写 junit 测试以及模拟,样例设置和带有示例的注解。

  1. Table of Contents
  2. 1\. Introduction
  3. 2\. Setting Up
  4. 3\. Annotations
  5. 4\. Example

1. Mockito 简介

在应用的单元测试期间,有时无法复制精确的生产环境。 有时数据库不可用,有时不允许网络访问。 可以有更多这样的限制。 为了解决这些限制,我们必须为这些不可用的资源创建模拟。

Mockito 是一个开放源代码框架,可让您轻松创建测试双打(模拟)。 对于您出于测试目的而替换生产对象的任何情况,双重测试是一个通用术语。

在模拟中,我们通常使用以下类型的测试双打。

  • 存根 – 是一个对象,该对象对测试期间执行的方法执行具有预定义的返回值。
  • 间谍 – 与存根相似的对象,但它们另外记录了它们的执行方式。
  • 模拟 – 是在测试期间对方法执行返回值并记录了对这些执行的期望的对象。 如果模拟人收到了他们不期望的电话,并且在验证过程中对其进行了检查,以确保他们收到了所有期望的电话,它们可能会引发异常。

我们可以在测试类中模拟接口和类。 Mockito 还可以在使用 Mockito 注解时帮助产生最少的样板代码。

2. Mockito 设置

要将 Mockito 添加到项目中,我们可以通过任何方式添加所需的 Mockito 版本,即 maven ,gradle 或 jar 文件

  1. <dependency>
  2. <groupId>org.mockito</groupId>
  3. <artifactId>mockito-core</artifactId>
  4. <version>2.23.4</version>
  5. <scope>test</scope>
  6. </dependency>
  1. testCompile group: 'org.mockito', name: 'mockito-core', version: '2.23.4'

下面给出了具有创建 Junit 测试以及 mockito 的所有依赖项的完整 pom 文件。 否则,我们需要查找并添加objenesishamcrest-corebyte-buddybyte-buddy-agentjunitmockito的匹配版本。

  1. <project xmlns="http://maven.apache.org/POM/4.0.0"
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <groupId>com.howtodoinjava.demo</groupId>
  6. <artifactId>MockitoExample</artifactId>
  7. <version>0.0.1-SNAPSHOT</version>
  8. <dependencies>
  9. <dependency>
  10. <groupId>org.mockito</groupId>
  11. <artifactId>mockito-core</artifactId>
  12. <version>2.23.0</version>
  13. <scope>test</scope>
  14. </dependency>
  15. <dependency>
  16. <groupId>junit</groupId>
  17. <artifactId>junit</artifactId>
  18. <version>4.12</version>
  19. <scope>test</scope>
  20. </dependency>
  21. </dependencies>
  22. </project>

3. Mockito 注解

在敲键盘来编写应用和单元测试之前,让我们快速概述有用的 Mockito 注解。

  • @Mock用于模拟创建。 它使测试类更具可读性。
  • @Spy用于创建间谍实例。 我们可以使用它代替spy(Object)方法。
  • @InjectMock用于自动实例化测试对象,并将所有@Mock@Spy带注解的字段依赖项注入其中(如果适用)。
  • @Captor用于创建参数捕获器

阅读更多: @Mock@InitMock注解之间的区别

要处理所有上述注解,MockitoAnnotations.initMock(testClass);必须至少使用一次。 要处理注解,我们可以使用内置运行器MockitoJUnitRunner或规则MockitoRule。 我们还可以在@Before带注解的 Junit 方法中显式调用initMock()方法。

  1. //1
  2. @RunWith(MockitoJUnitRunner.class)
  3. public class ApplicationTest {
  4. //code
  5. }
  1. //2
  2. public class ApplicationTest {
  3. @Rule public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_Stub);
  4. //code
  5. }
  1. //3
  2. public class ApplicationTest {
  3. @Before
  4. public void init() {
  5. MockitoAnnotations.initMock(this);
  6. }
  7. }

4. JUnit Mockito 示例

让我们学习编写将模拟程序用于依赖项的 junit 测试。 给定的示例具有RecordService,该文件在DatabaseDAONetworkDAO的帮助下将给定文件存储在数据库和网络位置中。

在测试环境中,无法访问数据库或网络位置,因此我们正在为两个仓库创建模拟。

  1. public class DatabaseDAO
  2. {
  3. public void save(String fileName) {
  4. System.out.println("Saved in database");
  5. }
  6. }
  1. public class NetworkDAO
  2. {
  3. public void save(String fileName) {
  4. System.out.println("Saved in network location");
  5. }
  6. }
  1. public class RecordService
  2. {
  3. DatabaseDAO database;
  4. NetworkDAO network;
  5. //setters and getters
  6. public boolean save(String fileName)
  7. {
  8. database.save(fileName);
  9. System.out.println("Saved in database in Main class");
  10. network.save(fileName);
  11. System.out.println("Saved in network in Main class");
  12. return true;
  13. }
  14. }

请记住,如果我们使用诸如 Spring 之类的任何 DI 框架,那么我们可能已经使用了注解@Autowired

要测试这个RecordService类,让我们创建一个单元测试。

  1. import static org.junit.Assert.assertEquals;
  2. import static org.mockito.Mockito.times;
  3. import static org.mockito.Mockito.verify;
  4. import org.junit.Test;
  5. import org.junit.runner.RunWith;
  6. import org.mockito.InjectMock;
  7. import org.mockito.Mock;
  8. import org.mockito.junit.MockitoJUnitRunner;
  9. import com.howtodoinjava.demo.mockito.DatabaseDAO;
  10. import com.howtodoinjava.demo.mockito.NetworkDAO;
  11. import com.howtodoinjava.demo.mockito.RecordService;
  12. @RunWith(MockitoJUnitRunner.class)
  13. public class ApplicationTest
  14. {
  15. @InjectMock
  16. RecordService recordService;
  17. @Mock
  18. DatabaseDAO databaseMock;
  19. @Mock
  20. NetworkDAO networkMock;
  21. @Test
  22. public void saveTest()
  23. {
  24. boolean saved = recordService.save("temp.txt");
  25. assertEquals(true, saved);
  26. verify(databaseMock, times(1)).save("temp.txt");
  27. verify(networkMock, times(1)).save("temp.txt");
  28. }
  29. }

让我们逐步了解以上测试类:

  • @RunWith(MockitoJUnitRunner.class)注解测试,以便 Mockito 可以处理注解。
  • 使用@Mock注解对 dao 字段进行注解,以为它们两个实例化一个模拟对象。
  • 使用@InjectMock注解对服务字段进行注解,以首先实例化然后注入两个模拟的依赖项。
  • 在要测试的类上调用方法进行测试,即recordService
  • 验证模拟对象中的方法已被调用。

还有许多其他方法可以测试方法和模拟的依赖项,我们将在以后的文章中介绍。

将有关此 junit Mockito2 示例的问题交给我。

学习愉快!

参考: Mockito Core Java 文档