Mockito and JUnit 5 – Using ExtendWith
1.简介
在这篇快速的文章中,我们将展示如何将Mockito与JUnit 5扩展模型集成。要了解有关JUnit 5扩展模型的更多信息,请查看本文。
首先,我们将展示如何创建一个扩展,该扩展自动为任何带有@Mock注释的类属性或方法参数创建模拟对象。
然后,我们将在JUnit 5测试类中使用Mockito扩展。
2. Maven依赖
2.1。必需的依存关系
让我们向我们的pom.xml中添加JUnit 5(木星)和ockockito依赖项:
1 2 3 4 5 6 7 8 9 10 11 12 | <dependency> <groupId>org.junit.jupiter</groupId> junit-jupiter-engine</artifactId> <version>5.3.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> mockito-core</artifactId> <version>2.21.0</version> <scope>test</scope> </dependency> |
请注意,junit-jupiter-engine是主要的JUnit 5库,junit-platform-launcheris与Maven插件和IDE启动器一起使用。
2.2。 Surefire插件
让我们还配置Maven Surefire插件,以使用新的JUnit平台启动器运行测试类:
1 2 3 4 5 6 7 8 9 10 11 | <plugin> maven-surefire-plugin</artifactId> <version>2.19.1</version> <dependencies> <dependency> <groupId>org.junit.platform</groupId> junit-platform-surefire-provider</artifactId> <version>1.0.1</version> </dependency> </dependencies> </plugin> |
2.3。 JUnit 4 IDE兼容性依赖性
为了使我们的测试用例与JUnit4(老式)兼容,对于尚不支持JUnit 5的IDE,让我们包括以下依赖项:
1 2 3 4 5 6 7 8 9 10 11 12 | <dependency> <groupId>org.junit.platform</groupId> junit-platform-runner</artifactId> <version>1.2.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.vintage</groupId> junit-vintage-engine</artifactId> <version>5.2.0</version> <scope>test</scope> </dependency> |
另外,我们应该考虑使用@RunWith(JUnitPlatform.class)注释所有测试类。
可以从Maven Central下载Junit-Jupiter-engine,junit-vintage-engine,junit-platform-launcher和mockito-core的最新版本。
3. Mockito扩展
Mockito为库中的JUnit5扩展提供了一个实现– mockito-junit-jupiter。我们将这种依赖关系包含在pom.xml中:
1 2 3 4 5 6 | <dependency> <groupId>org.mockito</groupId> mockito-junit-jupiter</artifactId> <version>2.23.0</version> <scope>test</scope> </dependency> |
4.建立测试类
让我们构建测试类并将Mockito扩展附加到它:
1 2 3 4 5 6 7 8 | @ExtendWith(MockitoExtension.class) @RunWith(JUnitPlatform.class) public class UserServiceUnitTest { UserService userService; ... // } |
我们可以使用@Mockannotation为可在测试类中任何地方使用的实例变量注入模拟:
1 | @Mock UserRepository userRepository; |
另外,我们可以将模拟对象注入到方法参数中:
1 2 3 4 5 6 7 8 9 10 | @BeforeEach void init(@Mock SettingRepository settingRepository) { userService = new DefaultUserService(userRepository, settingRepository, mailClient); Mockito.lenient().when(settingRepository.getUserMinAge()).thenReturn(10); when(settingRepository.getUserNameMinLength()).thenReturn(4); Mockito.lenient().when(userRepository.isUsernameAlreadyExists(any(String.class))).thenReturn(false); } |
请注意此处使用Mockito.lenient()。当执行期间测试方法之一未调用初始化的模拟时,Mockito会引发UnsupportedStubbingException。通过在初始化模拟时使用此方法,可以避免进行严格的存根检查。
我们甚至可以将模拟对象注入测试方法参数中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | @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); Assertions.assertNotNull(user.getId()); verify(mailClient).sendUserRegistrationMail(insertedUser); } |
请注意,我们作为测试参数注入的MailClient模拟将与我们在init方法中注入的实例不同。
5.结论
Junit 5提供了一个很好的扩展模型。我们演示了一个简单的Mockito扩展,简化了我们的模拟创建逻辑。
可以在GitHub项目的com.baeldung.junit5.mockito软件包中找到本文中使用的所有代码,以及一些其他的单元测试方法。