Mockito模拟泛型类XMLToObject失败,请求指导正确模拟方法
解决Mockito模拟泛型类XMLToObject无效的问题
看起来你遇到了两个核心问题:mock对象的方法没被触发(还是走了真实方法),以及调用时参数为null导致存根不匹配。下面一步步帮你解决:
问题根源分析
- mock对象未被正确使用:如果你的被测代码里是直接
new XMLToObject()而不是使用你创建的mockFoo,那Mockito的存根完全不会生效,自然会进入真实方法体。 - 参数匹配不匹配:当你用
when(mockFoo.xmlToObject(responseXml ,MyDetails.class))存根时,只有当调用方法时传入完全相同的responseXml字符串和MyDetails.class时,才会触发存根返回自定义对象。如果实际调用时传的xmlString是null,那参数不匹配,Mockito就会调用真实方法,这时候你看到的xmlString就是null。
修正步骤及代码示例
1. 确保被测代码使用mock对象
首先,你需要把mock的XMLToObject实例注入到被测类中,而不是让被测类自己创建真实实例。比如:
// 假设被测类是这样的 public class MyService { private XMLToObject<MyDetails> xmlConverter; // 通过构造方法注入(推荐) public MyService(XMLToObject<MyDetails> xmlConverter) { this.xmlConverter = xmlConverter; } public void doSomething(String xml) { JAXBElement<MyDetails> result = xmlConverter.xmlToObject(xml, MyDetails.class); // 后续逻辑 } } // 测试类中注入mock对象 @Test public void testDoSomething() { // 准备测试数据 String responseXml = "<myDetails><resultCode>000000</resultCode><resultDesc>done</resultDesc></myDetails>"; MyDetails resp = new MyDetails(); byte b1 = 0; resp.setResultCode(b1); resp.setResultDesc(""); JAXBElement<MyDetails> queryMyDetailsJaxb = new JAXBElement<>( new QName(MyDetails.class.getSimpleName()), MyDetails.class, resp); // 创建mock对象(泛型写法可以避免类型转换警告) XMLToObject<MyDetails> mockXmlConverter = Mockito.mock(XMLToObject.class); // 存根方法:这里可以根据实际情况选择参数匹配方式 // 方式1:精确匹配参数 when(mockXmlConverter.xmlToObject(responseXml, MyDetails.class)).thenReturn(queryMyDetailsJaxb); // 方式2:匹配任意字符串(如果不关心具体xml内容) // when(mockXmlConverter.xmlToObject(Mockito.anyString(), Mockito.eq(MyDetails.class))).thenReturn(queryMyDetailsJaxb); // 注入mock到被测类 MyService serviceUnderTest = new MyService(mockXmlConverter); // 执行测试方法 serviceUnderTest.doSomething(responseXml); // 验证方法是否被调用(可选) Mockito.verify(mockXmlConverter).xmlToObject(responseXml, MyDetails.class); }
2. 解决参数为null的问题
如果你的测试中调用xmlToObject时确实需要传null,那要调整存根的参数匹配:
// 当传入null作为xmlString时触发存根 when(mockXmlConverter.xmlToObject(Mockito.isNull(), Mockito.eq(MyDetails.class))).thenReturn(queryMyDetailsJaxb);
3. 避免泛型类型转换警告(可选)
如果你想彻底消除泛型转换的警告,可以用Mockito的@Mock注解配合测试运行器:
@RunWith(MockitoJUnitRunner.class) public class MyServiceTest { @Mock private XMLToObject<MyDetails> mockXmlConverter; @InjectMocks private MyService serviceUnderTest; @Test public void testDoSomething() { // 准备存根和测试逻辑 String responseXml = "<myDetails>...</myDetails>"; JAXBElement<MyDetails> queryMyDetailsJaxb = // 初始化你的返回对象 when(mockXmlConverter.xmlToObject(responseXml, MyDetails.class)).thenReturn(queryMyDetailsJaxb); serviceUnderTest.doSomething(responseXml); // 验证逻辑... } }
关键注意点
- 永远不要在被测代码中直接
new依赖类(比如XMLToObject),要通过依赖注入的方式传入,这样才能替换成mock对象。 - Mockito的存根是基于参数匹配的,确保存根的参数和实际调用的参数一致,或者使用匹配器(比如
anyString()、isNull())来匹配多种情况。 - 如果mock对象的方法还是进入了真实方法,那大概率是你没在被测代码中使用这个mock对象,一定要检查对象的引用是否正确。
内容的提问来源于stack exchange,提问作者Ravish
相关产品推荐
相关产品推荐

