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

Mockito中whenNew的替代方案:如何Mock AnotherClass对象

如何Mock方法内new出来的AnotherClass对象(无需PowerMockito)

针对你测试ClassToBeTested时遇到的问题,这里提供两种无需PowerMockito的可行方案:

方案一:使用Mockito 4.5+的MockConstruction API

如果你的项目使用Mockito 4.5.0及以上版本,可以直接用MockConstruction拦截AnotherClass的构造过程,生成Mock实例并配置行为:

测试代码示例

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedConstruction;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
class ClassToBeTestedTest {

    @Mock
    private DependencyOne dep1;

    @Mock
    private DependencyTwo dep2;

    @InjectMocks
    private ClassToBeTested classUnderTest;

    @Test
    void testMethod() {
        // 拦截AnotherClass的构造,生成Mock并配置行为
        try (MockedConstruction<AnotherClass> mockedConstruction = mockConstruction(AnotherClass.class,
                (mock, context) -> {
                    // 配置someAction不执行真实逻辑
                    doNothing().when(mock).someAction();
                })) {

            classUnderTest.method();

            // 验证构造出的Mock实例的someAction被调用
            AnotherClass constructedMock = mockedConstruction.constructed().get(0);
            verify(constructedMock).someAction();
        }
    }
}

注意事项

  • 必须确保Mockito版本≥4.5.0,MockConstruction是该版本正式引入的API
  • 使用try-with-resources语法,确保测试结束后自动清理Mock构造器,避免影响其他测试用例
  • 可以在构造回调中任意配置Mock的行为,比如抛出异常、返回特定值等

方案二:重构代码抽离对象创建逻辑(兼容低版本Mockito)

如果你的Mockito版本较低,无法使用MockConstruction,可以通过少量代码重构,把AnotherClass的创建逻辑抽成独立方法,再用Mockito的Spy来Mock这个方法:

第一步:修改待测试类

class ClassToBeTested {
    @Autowired
    DependencyOne dep1;
    @Autowired
    DependencyTwo dep2;

    void method(){
        AnotherClass anotherClass = createAnotherClass();
        anotherClass.someAction();
    }

    // 抽离对象创建逻辑,供测试时Mock
    protected AnotherClass createAnotherClass() {
        return new AnotherClass(dep1, dep2);
    }
}

第二步:编写测试代码

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
class ClassToBeTestedTest {

    @Mock
    private DependencyOne dep1;

    @Mock
    private DependencyTwo dep2;

    @Mock
    private AnotherClass mockAnotherClass;

    @InjectMocks
    @Spy
    private ClassToBeTested classUnderTest;

    @Test
    void testMethod() {
        // Mock抽离的创建方法,返回我们预定义的Mock实例
        doReturn(mockAnotherClass).when(classUnderTest).createAnotherClass();

        classUnderTest.method();

        // 验证someAction方法被调用
        verify(mockAnotherClass).someAction();
    }
}

优势

  • 兼容所有支持Spy功能的Mockito版本(基本是2.x及以上)
  • 重构后的代码更符合测试友好的设计,后续扩展也更灵活

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 14:23:15