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

Spring Boot服务方法单元测试问题:JUnit 5+Mockito测试失败

解决JUnit 5 + Mockito测试Spring Boot服务方法的问题

问题根源分析

报错核心原因是你尝试对非Mock对象调用when()存根方法:when(numberValue.length()).thenReturn(eq(16));。numberValue是普通String实例,并非Mockito创建的代理对象,Mockito只能Mock被它管控的对象方法。此外还有两处存根逻辑错误:

  • thenReturn(any())是错误用法:any()是参数匹配器,不能作为返回值使用,必须返回具体实例或确定值。
  • 若MyUtils/MyMapper仍存在静态调用逻辑,即使改成实例方法,也要确保服务类通过依赖注入使用实例,而非直接调用静态方法。

具体修复步骤

1. 移除无效的String方法存根

直接删掉when(numberValue.length()).thenReturn(eq(16));,你传入的numberValue本身就是16位字符串,filter条件会自动满足,完全不需要Mock。

2. 调整服务类的依赖注入方式

修改服务类,通过构造器注入MyUtils和MyMapper实例,替代原有的静态调用逻辑:

@Service
public class MyService {
    private final MyUtils myUtils;
    private final MyMapper myMapper;

    // 构造器注入(Spring推荐方式)
    public MyService(MyUtils myUtils, MyMapper myMapper) {
        this.myUtils = myUtils;
        this.myMapper = myMapper;
    }

    public Maybe<MyResponse> generate(String numberValue) {
        return Maybe.just(numberValue)
                .filter(number -> number.length() == Constants.REQUEST_REQUIRED)
                .flatMap(number -> myUtils.generate()) // 使用注入的实例调用方法
                .map(myMapper::createResponse) // 使用注入实例的方法引用
                .switchIfEmpty(Maybe.error(MyExceptioManager.throwException400(...)));
    }
}

3. 修正测试类的Mock逻辑

测试类中正确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.junit.jupiter.MockitoExtension;
import reactor.core.publisher.Maybe;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class) // 启用JUnit 5的Mockito支持
class MyServiceTest {

    @Mock
    private MyUtils myUtils; // Mock MyUtils实例

    @Mock
    private MyMapper myMapper; // Mock MyMapper实例

    @InjectMocks
    private MyService myService; // 将Mock自动注入到被测服务

    @Test
    void generate() {
        String numberValue = "1234567891234567";
        String mockGenerateResult = "模拟生成的字符串";
        MyResponse expectedResponse = new MyResponse("1234");

        // 存根MyUtils的generate方法,返回符合类型的Maybe对象
        when(myUtils.generate()).thenReturn(Maybe.just(mockGenerateResult));
        // 存根MyMapper的createResponse方法,返回预期的MyResponse实例
        when(myMapper.createResponse(anyString())).thenReturn(expectedResponse);

        myService.generate(numberValue)
                .test()
                .assertNoErrors()
                .assertComplete()
                .assertValue(response -> response.getCode().equals("1234"));
    }
}

关键注意事项

  • 若MyUtils.generate()返回Maybe类型,存根时必须返回Maybe.just(...),要严格匹配方法的返回值类型。
  • thenReturn()必须传入具体对象或确定值,any()这类匹配器仅能用于when()的方法参数中。
  • 测试类必须添加@ExtendWith(MockitoExtension.class),否则Mockito无法识别@Mock和@InjectMocks注解。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 21:32:29