Java17升级:JMockit测试代码转Mockito方案咨询
将JMockit测试转换为Mockito(适配Java 17)
1. 引入Mockito依赖
先在构建文件中添加Mockito核心依赖,若使用JUnit 5,还需集成JUnit Jupiter的适配包(以Maven为例):
<!-- Mockito核心依赖 --> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>4.11.0</version> <!-- 建议使用最新稳定版 --> <scope>test</scope> </dependency> <!-- JUnit 5集成包(JUnit 5环境下添加) --> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-junit-jupiter</artifactId> <version>4.11.0</version> <scope>test</scope> </dependency>
2. 改造测试类
JMockit通过MockUp实现类级Mock,Mockito则侧重实例级的Mock/Spy。根据测试需求分两种场景改造:
场景1:完全Mock Client类(所有方法用模拟实现)
如果测试不需要Client的真实逻辑,仅需模拟clentDetail方法:
import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.Mockito.when; public class Test { // 声明Mock实例 @Mock private Client client; @Before public void init() { // 初始化Mockito注解 MockitoAnnotations.openMocks(this); mockClient(true, true); } private void mockClient(boolean arg1, boolean arg2) { // 模拟clentDetail方法的行为 when(client.clentDetail(anyMap())).thenAnswer(invocation -> { ClientTO clientTO = new ClientTO(); // 迁移原JMockit中的模拟逻辑,比如根据arg1/arg2设置属性 if (arg1) { clientTO.setSomeField("mockValue1"); } if (arg2) { clientTO.setAnotherField("mockValue2"); } // 原代码中do something的逻辑移至此处 return clientTO; }); } // 测试方法示例 @Test public void testClientDetail() { ClientTO result = client.clentDetail(Map.of("testKey", "testValue")); // 后续断言逻辑... } }
场景2:部分Mock Client类(仅替换clentDetail方法,其他方法保留真实逻辑)
若需要保留Client其他方法的真实实现,仅替换clentDetail,使用Spy:
import org.junit.Before; import org.junit.Test; import org.mockito.Spy; import org.mockito.MockitoAnnotations; import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.Mockito.doAnswer; public class Test { // 基于真实对象创建Spy实例 @Spy private Client client = new Client(); @Before public void init() { MockitoAnnotations.openMocks(this); mockClient(true, true); } private void mockClient(boolean arg1, boolean arg2) { // 用doAnswer避免触发真实方法逻辑 doAnswer(invocation -> { ClientTO clientTO = new ClientTO(); // 迁移原JMockit中的模拟逻辑 if (arg1) { clientTO.setSomeField("mockValue1"); } if (arg2) { clientTO.setAnotherField("mockValue2"); } return clientTO; }).when(client).clentDetail(anyMap()); } // 测试方法示例 @Test public void testClientDetailWithSpy() { ClientTO result = client.clentDetail(Map.of("testKey", "testValue")); // 后续断言逻辑... } }
3. Java 17适配注意事项
- 模块权限:若项目使用Java模块(
module-info.java),需允许Mockito访问被测试类,在module-info.java中添加:
或在测试运行时添加VM参数:opens com.your.package to org.mockito;--add-opens com.your.package/com.your.package.client=org.mockito - 参数匹配:若需要精确匹配Map参数,替换
anyMap()为eq(targetMap)或自定义匹配器。 - 方法拼写:注意原代码中方法名是
clentDetail(疑似少写一个i),若为拼写错误建议统一修正,避免后续问题。
内容的提问来源于stack exchange,提问作者Arushi
相关产品推荐
相关产品推荐

