You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:15:58