如何在Mockito 5.9中从模拟构造返回真实对象?
Mockito 5.9构造模拟返回指定实例的正确方式
这不是Mockito的Bug,而是你对mockConstruction的API用法理解存在偏差。mockConstruction的核心作用是拦截构造函数调用,为每次new操作创建新的Mock/Spy对象,并允许你配置这些对象的行为;它并不直接支持让new返回你预先创建好的实例。
错误尝试的原因解析
- 第一种尝试:
spiedInstance(spy)是指定新创建的Spy对象的基础实例,但Mockito会在每次new Foo(0)时,基于传入的构造参数(0)创建新的Spy,而非复用你预先创建的new Foo(5)实例,因此getField()返回0。 - 第二种尝试:
useConstructor(5)是指定Mock对象创建时使用的构造参数,但它不会覆盖你调用new Foo(0)时传入的参数,最终创建的对象仍基于参数0初始化。 - 第三种尝试:预先创建的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
相关产品推荐
相关产品推荐

