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

如何在JUnit+Mockito中仅Mock MyClass调用的Problematic构造方法?

仅Mock指定调用方的Problematic构造方法解决方案

针对你的需求,Mockito 5.5.0提供的MockedConstruction可以通过过滤逻辑精准控制哪些构造调用被Mock,完全满足"第三方库构造保留原行为、MyClass构造Mock"的约束。以下是两种可行方案:

方案1:通过构造参数过滤(简单直接)

如果MyClass和第三方库传入的构造参数唯一,可直接通过参数匹配来拦截目标构造调用:

class MockProblematicObjectConstructionTest {

    @Test
    void testMyClassProblematicMock() {
        try (MockedConstruction<Problematic> mockedProblematic = mockConstruction(
                Problematic.class,
                // 仅拦截参数为"this needs to be mocked"的构造调用
                context -> "this needs to be mocked".equals(context.arguments().get(0)),
                (mock, context) -> {
                    // 为Mock实例设置自定义行为,比如抛出异常
                    Mockito.doThrow(new RuntimeException("Mocked construction failure")).when(mock);
                })) {
            MyClass.myCode();
            
            // 验证MyClass触发的构造被Mock(仅1个Mock实例)
            assertEquals(1, mockedProblematic.constructed().size());
            // 第三方库的构造会执行真实逻辑,控制台会输出"Problematic object constructed: this is fine"
        }
    }
}

核心逻辑

  • 使用mockConstruction的重载方法,传入Predicate<Context>作为过滤条件:返回true则Mock该构造,返回false则执行真实构造。
  • 第三方库传入的参数是"this is fine",过滤条件不匹配,因此保留原构造逻辑;MyClass的参数匹配,触发Mock行为。

方案2:通过调用栈过滤(更可靠)

如果构造参数可能重复,可通过调用栈判断构造调用的发起者,精准定位MyClass触发的构造:

class MockProblematicObjectConstructionTest {

    @Test
    void testMyClassProblematicMockByCaller() {
        try (MockedConstruction<Problematic> mockedProblematic = mockConstruction(
                Problematic.class,
                // 过滤调用栈中包含MyClass.myCode的构造调用
                context -> {
                    for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
                        if ("MyClass".equals(element.getClassName()) && "myCode".equals(element.getMethodName())) {
                            return true;
                        }
                    }
                    return false;
                },
                (mock, context) -> {
                    // 设置Mock行为,比如抛出异常
                    Mockito.doThrow(new RuntimeException("Mocked construction failure")).when(mock);
                })) {
            MyClass.myCode();
            
            // 验证Mock实例数量
            assertEquals(1, mockedProblematic.constructed().size());
        }
    }
}

核心逻辑

  • 遍历当前线程的调用栈,检查是否存在MyClass.myCode的调用记录,以此判断构造发起者。
  • 仅对MyClass触发的构造进行Mock,完全不影响第三方库的构造逻辑。

关键注意事项

  • 两种方案均满足你的约束:第三方库的Problematic实例保持真实构造,MyClass的实例可自定义Mock行为(如抛异常)。
  • 方案1性能更优,适合参数唯一的场景;方案2不依赖参数,适用于复杂的调用场景。

内容的提问来源于stack exchange,提问作者Danilo Piazzalunga

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 02:04:51