1. 概述
在本篇快速教程中,我们将展示 如何将 Mockito 与 JUnit 5 的扩展模型集成。如果你对 JUnit 5 的扩展机制还不太熟悉,可以先参考这篇 文章。
我们会先介绍如何编写一个扩展,自动为类属性或方法参数上标注了 @Mock
注解的字段创建 Mock 对象。
然后,我们会在一个 JUnit 5 测试类中实际使用这个 Mockito 扩展。
2. Maven 依赖
首先,我们需要在 pom.xml
中添加 JUnit 5(即 jupiter)和 mockito 相关依赖:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.10.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
此外,为了支持 JUnit 5 风格的 Mockito 扩展,还需要引入:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
3. 构建测试类
接下来我们构建一个测试类,并通过 @ExtendWith
注解挂载 Mockito 扩展:
@ExtendWith(MockitoExtension.class)
class UserServiceUnitTest {
UserService userService;
// ...
}
我们可以使用 @Mock
注解来注入一个 Mock 实例变量,在整个测试类中都可以使用:
@Mock UserRepository userRepository;
也可以将 Mock 对象注入到方法参数中:
@BeforeEach
void init(@Mock SettingRepository settingRepository) {
userService = new DefaultUserService(userRepository, settingRepository, mailClient);
lenient().when(settingRepository.getUserMinAge()).thenReturn(10);
when(settingRepository.getUserNameMinLength()).thenReturn(4);
lenient().when(userRepository.isUsernameAlreadyExists(any(String.class)))
.thenReturn(false);
}
⚠️ 注意这里使用了 lenient()
方法。默认情况下,Mockito 会在初始化的 Mock 没有被任何一个测试方法调用时抛出 UnsupportedStubbingException
。使用 lenient()
可以跳过这种严格的 Stub 校验。
我们甚至可以在单个测试方法的参数中注入 Mock 对象:
@Test
void givenValidUser_whenSaveUser_thenSucceed(@Mock MailClient mailClient) {
// Given
user = new User("Jerry", 12);
when(userRepository.insert(any(User.class))).then(new Answer<User>() {
int sequence = 1;
@Override
public User answer(InvocationOnMock invocation) throws Throwable {
User user = (User) invocation.getArgument(0);
user.setId(sequence++);
return user;
}
});
userService = new DefaultUserService(userRepository, settingRepository, mailClient);
// When
User insertedUser = userService.register(user);
// Then
verify(userRepository).insert(user);
assertNotNull(user.getId());
verify(mailClient).sendUserRegistrationMail(insertedUser);
}
⚠️ 需要注意的是,作为测试方法参数注入的 MailClient
Mock 实例,和 init
方法中注入的并不是同一个对象。
4. 小结
JUnit 5 提供了非常灵活且强大的扩展模型。我们展示了如何使用 Mockito 扩展来简化 Mock 对象的创建逻辑。
✅ 本文所有代码均可在我们的 GitHub 项目 中找到。