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

仅调用其他服务类方法的Service类是否需要测试?该如何实现?

结论:需要为myMethod编写测试

为什么需要测试

  • 验证编排逻辑正确性:OtherService各方法的单测只能保证方法本身逻辑正确,无法覆盖myMethod的编排逻辑:比如三个方法的调用顺序是否符合预期、是否漏调用某方法、入参传递是否正确(比如method2第二个参数是input.getParameter(),如果写错传成input本身,OtherService的单测完全覆盖不到这个问题)
  • 覆盖异常分支:比如method1抛出异常时,后续方法是否会执行这类流程逻辑,也需要单独测试验证
  • 防护回归:后续代码迭代时如果有人误修改myMethod的逻辑,单测可以第一时间发现问题

测试实现方案

你使用的Junit5+Mockito组合完全可以实现轻量的单元测试,不需要启动Spring上下文,执行效率很高。首先确认spring-boot-starter-test依赖已经引入,Spring Boot 2.3.3版本的starter默认已经集成了Junit5、Mockito相关依赖,不需要额外引入。

测试代码示例如下:

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

import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
public class MyServiceClassTest {

    // 模拟依赖的OtherServiceClass,不需要真实实例
    @Mock
    private OtherServiceClass otherServiceClass;

    // 自动将模拟依赖注入到待测试的MyServiceClass中
    @InjectMocks
    private MyServiceClass myServiceClass;

    @Test
    void myMethod_shouldInvokeAllMethodsInOrderWithCorrectParams() {
        // 1. 构造测试入参
        Object testInput = mock(Object.class);
        Object testParam = new Object();
        when(testInput.getParameter()).thenReturn(testParam);

        // 2. 调用待测试方法
        myServiceClass.myMethod(testInput);

        // 3. 按顺序验证三个方法的调用情况、入参是否正确
        InOrder inOrder = inOrder(otherServiceClass);
        inOrder.verify(otherServiceClass).method1(eq(testInput));
        inOrder.verify(otherServiceClass).method2(eq(testInput), eq(testParam));
        inOrder.verify(otherServiceClass).method3();
    }

    @Test
    void myMethod_shouldStopInvokeWhenMethod1ThrowException() {
        // 1. 构造异常场景:method1调用时抛出异常
        Object testInput = mock(Object.class);
        doThrow(new RuntimeException("mock exception")).when(otherServiceClass).method1(any());

        // 2. 调用方法并断言抛出异常
        org.junit.jupiter.api.Assertions.assertThrows(RuntimeException.class, () -> myServiceClass.myMethod(testInput));

        // 3. 验证后续方法没有被调用
        verify(otherServiceClass, never()).method2(any(), any());
        verify(otherServiceClass, never()).method3();
    }
}

说明:如果测试入参是自定义的业务类,也可以直接构造真实对象而非mock对象,根据你的业务场景灵活选择即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 19:15:02