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

如何在Mockito 5.9中从模拟构造返回真实对象?

Mockito 5.9构造模拟返回指定实例的正确方式

这不是Mockito的Bug,而是你对mockConstruction的API用法理解存在偏差。mockConstruction的核心作用是拦截构造函数调用,为每次new操作创建新的Mock/Spy对象,并允许你配置这些对象的行为;它并不直接支持让new返回你预先创建好的实例。

错误尝试的原因解析

  1. 第一种尝试:spiedInstance(spy)是指定新创建的Spy对象的基础实例,但Mockito会在每次new Foo(0)时,基于传入的构造参数(0)创建新的Spy,而非复用你预先创建的new Foo(5)实例,因此getField()返回0。
  2. 第二种尝试:useConstructor(5)是指定Mock对象创建时使用的构造参数,但它不会覆盖你调用new Foo(0)时传入的参数,最终创建的对象仍基于参数0初始化。
  3. 第三种尝试:预先创建的Spy实例不会被mockConstruction复用,每次new操作仍会生成新的Spy对象,结果自然不符合预期。

正确实现方式

如果你需要让new Foo(...)生成的对象返回指定值(比如getField()返回5),可以在mockConstruction的回调中存根目标方法:

private static class Foo {
    private final int field;

    Foo(int field) {
        this.field = field;
    }

    int getField() {
        return field;
    }
}

@Test
public void testMockConstructionStubMethod() {
    try (var ignored = mockConstruction(Foo.class, (mock, context) -> {
        // 存根getField方法,固定返回5
        Mockito.when(mock.getField()).thenReturn(5);
    })) {
        Foo foo = new Foo(0);
        Assert.assertEquals(5, foo.getField());
    }
}

如果需要让对象保留真实方法逻辑,但修改最终返回的结果(比如忽略构造参数,使用固定值初始化),由于field是final无法直接修改,同样通过存根方法实现即可。

特殊需求说明

如果你的需求是让所有new Foo(...)直接返回同一个预先创建的真实对象,Mockito的mockConstruction无法直接实现(它的机制是每次创建新的Mock/Spy)。这种场景下可以考虑使用PowerMock的whenNew API,或者调整测试策略规避这种需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 01:06:02