首页 > 解决方案 > 如何测试返回 Mono 的函数其中有另一个 Mono在使用 Reactor 的 StepVerifier

问题描述

我有一个这样的 ServiceWebClientInterface.java

import reactor.core.publisher.Mono;

public interface ServiceWebClientInterface {

    Mono<String> apiCall();
}

MyClass.java

import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;

public class MyClass extends AbstractGatewayFilterFactory<MyClass.Config> {

    private final ServiceWebClientInterface serviceWebClientInterface;

    MyClass(final ServiceWebClientInterface serviceWebClientInterface) {
        this.serviceWebClientInterface = serviceWebClientInterface;
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            return serviceWebClientInterface.apiCall().flatMap(response -> {
                if (!"Valid".equals(response)) {
                    exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
                    return exchange.getResponse().setComplete();
                }
                return chain.filter(exchange);
            });

        };
    }

    public static class Config  {
        // Put the configuration properties
    }
}

我正在尝试使用 StepVerifier 对 myMethod 进行单元测试,但我无法在 myMethod 的内部 lambda 函数中执行语句。

MyClassTest.java

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;

import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;
class MyClassTest {

    @Mock
    ServiceWebClientInterface mockServiceWebClientInterface;
    @Mock
    private ServerWebExchange mockServerWebExchange;
    @Mock
    private GatewayFilterChain mockGatewayFilterChain;
    @Mock
    private ServerHttpResponse mockServerHttpResponse;

    @BeforeEach
    void setup() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    void test_apply_forValid() {
        when(mockServiceWebClientInterface.apiCall()).thenReturn(Mono.just("Valid"));
        MyClass.Config config = new MyClass.Config();
        MyClass myClass = new MyClass(mockServiceWebClientInterface);

        GatewayFilter gatewayFilter = myClass.apply(config);

        Mono<Void> response = gatewayFilter.filter(mockServerWebExchange, mockGatewayFilterChain);

        StepVerifier.create(response).expectComplete();

        verify(mockServiceWebClientInterface).apiCall();
        verify(mockGatewayFilterChain).filter(mockServerWebExchange);

    }

    @Test
    void test_apply_forInValid() {
        when(mockServiceWebClientInterface.apiCall()).thenReturn(Mono.just("InValid"));
        when(mockServerWebExchange.getResponse()).thenReturn(mockServerHttpResponse);
        MyClass.Config config = new MyClass.Config();
        MyClass myClass = new MyClass(mockServiceWebClientInterface);

        GatewayFilter gatewayFilter = myClass.apply(config);

        Mono<Void> response = gatewayFilter.filter(mockServerWebExchange, mockGatewayFilterChain);

        StepVerifier.create(response).expectComplete();

        verify(mockServiceWebClientInterface).apiCall();
        verify(mockServerHttpResponse).setStatusCode(eq(HttpStatus.FORBIDDEN));
        verify(mockServerHttpResponse).setComplete();
        verify(mockGatewayFilterChain, never()).filter(mockServerWebExchange);

    }


}

请在上面找到完整的代码,当我运行测试时,我观察到内部 lambda 函数没有被使用步骤验证器调用。

标签: javareactive-programmingspring-webfluxproject-reactorspring-reactor

解决方案


我猜你想测试实现MyLambda接口的类。serviceWebClientInterface正如代码片段中提到的那样,您肯定会在那里注入。

要对该类进行单元测试,您应该模拟serviceWebClientInterface.apiCall()并验证它是否被调用。作为您实际代码片段的补充。

您可以为此目的使用 Mockito 库。

  • 创建一个模拟:

given(serviceWebClientInterface).willReturn(Mono.just("some text"));

  • 然后验证它是否被调用:

verify(serviceWebClientInterface).apiCall()


推荐阅读