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

如何使用Mockito框架为Java服务编写when...thenReturn模式的Mock测试

调整思路与实现方案

第一步:修改业务代码适配Mock逻辑

你当前CodeConfigBuilder直接通过@Value读取配置,没有依赖你定义的PropertySourceResolver,导致Mock的配置类无法注入生效,先调整依赖关系:

@Component
public class CodeConfigBuilder {
    // 移除@Value注入的字段,改为依赖配置读取类
    private final PropertySourceResolver propertySourceResolver;

    // 构造器注入,Mockito可以通过构造器自动注入Mock对象
    public CodeConfigBuilder(PropertySourceResolver propertySourceResolver) {
        this.propertySourceResolver = propertySourceResolver;
    }

    public void validateRequestAndSetDefaults(PromoRequest promoRequest) {
        prefixAndPostFixControlAccordingToLength(promoRequest);
    }

    private void prefixAndPostFixControlAccordingToLength(PromoRequest promoRequest) {
        if (promoRequest.getPostfix() != null) {
            // 从配置类读取前缀长度
            int lengthControl = propertySourceResolver.getPrefixLength() + promoRequest.getPostfix().length();
            if (lengthControl >= promoRequest.getLength()) {
                throw new BadRequestException(Constant.ClientConstants.THE_SUM_OF_PREFIX_AND_POSTFIX_CAN_NOT_BE_GREATER_THAN_LENGHT);
            }
        }    
    }
}

第二步:重写测试类,使用when...thenReturn打桩

你之前的测试类注解、依赖注入逻辑都存在错误,调整后代码如下:

@RunWith(MockitoJUnitRunner.class)
class CodeConfigBuilderTest {
    // 纯Mockito单元测试用@Mock即可,@MockBean是SpringBoot测试注解
    @Mock
    private PropertySourceResolver propertySourceResolver;
    // @InjectMocks标注在要测试的目标类上,会自动将@Mock的对象注入进去
    @InjectMocks
    private CodeConfigBuilder codeConfigBuilder;

    private PromoRequest promoRequest;

    @Before
    public void init() {
        promoRequest = new PromoRequest();
        promoRequest.setPrefix("ABC");
        promoRequest.setPostfix("ABCDABCD"); // 后缀长度为8
        promoRequest.setQuantity(10);
        promoRequest.setLength(12);
        promoRequest.setCharset("ABCDEF");
    }

    // 测试正常场景:前缀+后缀长度小于总长度,验证不抛异常
    @Test
    public void validateRequest_shouldSuccess_whenSumLengthValid() {
        // 打桩:指定调用getPrefixLength时返回3
        when(propertySourceResolver.getPrefixLength()).thenReturn(3);
        // 执行待测方法 3+8=11 <12 符合规则
        codeConfigBuilder.validateRequestAndSetDefaults(promoRequest);
    }

    // 测试异常场景:前缀+后缀长度大于等于总长度,验证抛出预期异常
    @Test(expected = BadRequestException.class)
    public void validateRequest_shouldThrowException_whenSumLengthInvalid() {
        // 打桩:指定调用getPrefixLength时返回4,4+8=12 >=12 触发异常
        when(propertySourceResolver.getPrefixLength()).thenReturn(4);
        codeConfigBuilder.validateRequestAndSetDefaults(promoRequest);
    }
}

核心逻辑说明

  • 所有外部依赖(配置读取、第三方调用等)都抽成可注入的Bean,才能通过Mockito模拟返回值,不需要加载Spring上下文和真实配置文件,测试用例更稳定
  • when...thenReturn的作用是自定义Mock对象的方法返回值,可灵活调整返回值覆盖所有正常、边界、异常场景,不需要修改配置文件就能完成全场景测试

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 08:15:05