如何正确为依赖外部服务的业务方法编写单元测试

在单元测试中,应聚焦于被测类自身的逻辑行为,而非其依赖服务的内部实现;对 ServiceA 的测试需覆盖 ServiceB 方法返回 true、false 和抛出异常三种场景,以验证其调用链的健壮性与正确性。

在单元测试中,应聚焦于被测类自身的逻辑行为,而非其依赖服务的内部实现;对 ServiceA 的测试需覆盖 ServiceB 方法返回 true、false 和抛出异常三种场景,以验证其调用链的健壮性与正确性。

当 ServiceA 调用 ServiceB.shouldVerify() 仅获取一个布尔值,并将其透传给下游服务(无条件分支或业务判断),看似逻辑简单,但这恰恰是单元测试的关键覆盖点——因为 ServiceA 的行为正确性高度依赖于它如何响应 ServiceB 的各种输出状态。

✅ 正确做法:在 ServiceA 的单元测试中,使用 Mock 框架(如 Mockito)隔离 ServiceB,并显式验证以下三种核心场景:

示例(JUnit 5 + Mockito):

@ExtendWith(MockitoExtension.class)
class ServiceATest {

    @Mock
    private ServiceB serviceB;

    @InjectMocks
    private ServiceA serviceA;

    @Test
    void foo_shouldProcessWhenServiceBReturnsTrue() {
        // given
        when(serviceB.shouldVerify(any())).thenReturn(true);

        // when
        serviceA.foo();

        // then
        verify(serviceC).process(true); // 假设后续调用 serviceC.process(value)
    }

    @Test
    void foo_shouldHandleFalseResponse() {
        when(serviceB.shouldVerify(any())).thenReturn(false);
        serviceA.foo();
        verify(serviceC).process(false);
    }

    @Test
    void foo_shouldPropagateServiceBException() {
        when(serviceB.shouldVerify(any())).thenThrow(new RuntimeException("Timeout"));

        assertThatThrownBy(() -> serviceA.foo())
            .isInstanceOf(RuntimeException.class)
            .hasMessage("Timeout");
    }
}

⚠️ 注意事项:

总结:单元测试的本质是保障被测类在可控边界内的行为确定性。ServiceA 虽不包含复杂业务规则,但它作为服务编排层,承担着连接、转换与容错职责。对其开展多态响应测试(true/false/exception),是构建高可靠性微服务架构不可或缺的一环。

本文转载于:互联网 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。