测试基础 Java Mocking 神器 | Mockito 测试框架的一些实践体会

TesterHome小助手 · 2023年04月13日 · 3569 次阅读

背景:Mockito 是一个 Java 单元测试开发框架。在写测试单元时它可以 Mock(模拟)开发中一些未完成的接口或者网络断开、数据库连接错误等方法调用。Mockito 的可读性非常好,不会让你感到迷惑,产生的验证错误也很明确。以下为作者的一些使用体会,供大家参考。

作者|Samuel Catalano,软件工程师(巴西)
编译整理|TesterHome 社区

Mockito 是一个流行的 Java 测试框架,开发人员通过它能够为单元测试创建模拟对象,通过模拟外部依赖关系的行为,使得单独测试单个组件成为可能。这对于测试复杂的系统特别有用,特别是那些外部依赖的行为是不可预测的或难以控制的系统。

使用模拟对象进行隔离测试

使用 Mockito 的第一步是为代码中的依赖关系创建模拟对象。通过隔离测试每个单元,可以直接验证它而不依赖于外部依赖。这使得在开发过程的早期识别和修复任何问题变得更加容易。

验证行为,而不是实现

当测试一个方法时,重要的是关注该方法的行为,而不是其实现细节。这有助于确保测试的健壮性和可维护性,同时也更容易在不影响测试的情况下对实现进行修改。

使用 ArgumentCaptor 进行复杂的参数匹配

ArgumentCaptor 是 Mockito 的一个强大的功能,能够以一种更灵活和可读的方式捕获和验证方法参数。这在测试复杂参数的方法时特别有用,比如集合或自定义对象。

使用 thenCallRealMethod

thenCallRealMethod() 是 Mockito 的一个功能,它允许调用一个方法的真正实现,而不是模拟的版本。虽然这在某些情况下很有用,但要谨慎使用这个功能,虽然在一定程度测试更加连贯,但也更难理解。

使用注解,如@Mock@InjectMocks

Mockito 提供了几个注解,如@Mock@InjectMocks,可以让创建和注入模拟对象到你的测试中更加容易。通过使用这些注解,可以减少设置测试所需的模板代码量,并使测试更具可读性。

避免使用 reset()

Reset 是 Mockito 的一个功能,它可以让你清除一个模拟对象的状态。虽然这在某些情况下是有用的,但重要的是要谨慎使用它,因为它可以使测试变得脆弱和难以理解。一个更好的方法是使用像@Before这样的注解,在每次测试前创建一个新的模拟对象。

代码示例

这里有一个代码例子,演示了一些使用 Mockito 的实践。

import static org.mockito.Mockito.*;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

public class ExampleTest {

   @Mock
   private Dependency dependency;

   @InjectMocks
   private Service service;

   @Captor
   private ArgumentCaptor<String> argumentCaptor;

   @Before
   public void setup() {
      MockitoAnnotations.initMocks(this);
   }

   @Test
   public void testService() {
      // arrange
      when(dependency.doSomething("input")).thenReturn("output");

      // act
      String result = service.useDependency("input");

      // assert
      verify(dependency).doSomething(argumentCaptor.capture());
      assertEquals("input", argumentCaptor.getValue());
      assertEquals("output", result);
   }
}

在这个例子中,使用@Mock注解来为 Dependency 类创建一个模拟对象。使用@InjectMocks注解来将模拟对象注入到服务类的实例中,可以单独地测试服务类,而非必须依赖类的行为。

我们还使用@Captor注解来创建一个 ArgumentCaptor 对象,可以捕获并验证传递给 Dependency 类的 doSomething 方法的参数。与使用 eq 或其他参数匹配器相比,这是一种更加灵活和可读的方式来测试传递给方法的参数。

在 testService 方法中,使用 when 方法来实现 doSomething 方法的模拟和被调用时的返回结果。还使用验证方法来验证 doSomething 方法是用预期的参数调用的。最后,使用 assertEquals 方法来验证 useDependency 方法的结果。

总结

Mockito 是一个强大的 Java 测试框架,它能够让开发者给单元测试创建模拟对象。通过遵循好的实践经验,可以确保测试是健壮的、可维护的,并且易于理解。无论你是在测试复杂的系统还是简单的组件,Mockito 都可以帮助你验证代码的行为,并在开发过程中及早发现任何问题。

Mockito 官方信息
https://site.mockito.org/

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册