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

Mockito未Stub目标方法,反而执行了EncService.callFn实际逻辑

解决Mockito模拟EncService.callFn方法时实际逻辑被执行的问题

问题核心原因

你遇到的问题根源在于ServiceClass的sendPayload方法内部直接new了EncService实例,而非通过依赖注入获取实例。Mockito的@Mock和@InjectMocks仅能作用于通过构造器、setter或字段注入的依赖对象,对于方法内直接new出来的对象,Mockito无法拦截替换,导致测试类中模拟的encService和实际代码使用的是两个完全独立的对象,模拟自然失效,实际逻辑会被执行。

解决方案

方案1:修改ServiceClass,采用依赖注入(推荐)

重构ServiceClass,将EncService作为类的依赖,而非在方法内创建实例,最常用的方式是构造器注入:

public class ServiceClass {
    private final EncSercice encService;

    // 通过构造器注入依赖
    public ServiceClass(EncSercice encService) {
        this.encService = encService;
    }

    public void sendPayload(final ValidRequest req) {
        // some code imp..
        // 使用注入的encService实例,不再手动new
        String str = encService.callFn(req, keys);
    }
}

方案2:调整测试类,确保Mock对象被正确注入

修改后的ServiceClass会通过构造器接收EncService实例,此时测试类的@InjectMocks会自动将@Mock创建的encService注入到ServiceClass中。若使用JUnit 5,推荐用@ExtendWith(MockitoExtension.class)替代手动初始化Mock:

import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
public class ClassA {

    @Mock
    EncSercice encService;

    @InjectMocks
    ServiceClass service;

    @Test
    public void testEncryptRegisterTransactionPayload() {
        ValidRequest request = new ValidRequest();

        try {
            when(encService.callFn(anyString(), any(String[].class)))
                    .thenReturn("Stubbed encrypted message");

            service.sendPayload(request);
            verify(encService).callFn(anyString(), any(String[].class));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

方案3:临时方案(不推荐):使用PowerMock拦截new操作

若无法修改ServiceClass代码,可通过PowerMock拦截方法内的new操作,强制返回Mock对象。但该方式会修改字节码,增加测试维护成本,仅作为临时解决方案:

// 需引入PowerMock相关依赖
@RunWith(PowerMockRunner.class)
@PrepareForTest(ServiceClass.class)
public class ClassA {

    @Mock
    EncSercice encService;

    @InjectMocks
    ServiceClass service;

    @Test
    public void testEncryptRegisterTransactionPayload() throws Exception {
        ValidRequest request = new ValidRequest();

        // 拦截ServiceClass内new EncSercice()的操作,返回Mock对象
        whenNew(EncSercice.class).withNoArguments().thenReturn(encService);
        when(encService.callFn(anyString(), any(String[].class)))
                .thenReturn("Stubbed encrypted message");

        service.sendPayload(request);
        verify(encService).callFn(anyString(), any(String[].class));
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 04:29:57