繁体   English   中英

Spring Webflux 中的模拟 flatMap ServerResponse 主体

[英]Mock flatMap ServerResponse Body in Spring Webflux

我正在运行 Spring Webflux 应用程序,因此我使用 flatMap 来转换我的请求正文。 我有一个看起来像这样的路由器,

@Configuration
public class TallyRouter {
    private static final String TALLY_BASE_URL = "/admin/tally";
    private static final String TALLY_ID_URL = "/{tallyId}";

    @Bean
    RouterFunction<ServerResponse> tallyRoutes(tallyHandler handler) {
        return RouterFunctions.route(GET(TALLY_CONFIG_BASE_URL + "/active"), handler::getActiveTally)
                .andRoute(POST(TALLY_BASE_URL).and(accept(MediaType.APPLICATION_JSON)), handler::createTally);
}

我的处理程序 class 看起来像这样,

@Component
@RequiredArgsConstructor
public class TallyHandler {

    @Autowired
    TallyService tallyService;

    private static final Logger logger = LogManager.getLogger(TallyHandler.class);

    public Mono<ServerResponse> createTally(ServerRequest request) {
        Mono<NewTallyRequest> req = request.bodyToMono(NewTallyRequest.class);
        return req
                .doOnNext(result -> logger.info(result))
                .flatMap(a -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
                        .body(tallyService.createTally(a, request.exchange()), String.class));   // the line of the code that is null
    }
}

这就是我的测试的样子,

@ExtendWith(MockitoExtension.class)
@WebFluxTest
@ContextConfiguration(classes = { TallyHandler.class, TallyRouter.class })
@ActiveProfiles("test")
class TallyHandlerTest {

    @MockBean
    WebClient webClient;

    @MockBean
    TallyService tallyService;

    @Autowired
    private ApplicationContext context;

    WebTestClient webTestClient;

    MockWebServer mockWebServer;

    String res = "testRes";

    @BeforeEach
    void before() throws IOException {

        webTestClient = WebTestClient.bindToApplicationContext(this.context).configureClient().build();

        mockWebServer = new MockWebServer();
        mockWebServer.start();
    }

    @AfterEach
    void tearDown() throws IOException {
        mockWebServer.close();
    }

    @Test
    @WithMockUser(roles = "ADMIN")
    void createTallyTest_200() {
        String url = "/admin/tally";

        MockResponse mockedResponse = new MockResponse().setStatus("200").setBody(res);
        mockWebServer.enqueue(mockedResponse);

        NewTallyRequest req = new NewTallyRequest();
        req.setIsActive(isActive);

        when(tallyService.createTally(req, exchange)).thenReturn(Mono.just(res));

        webTestClient.mutateWith(csrf()).post().uri(uriBuilder -> uriBuilder.path(url).build())
                .body(BodyInserters.fromValue(req)).exchange().expectStatus().is2xxSuccessful();
    }
}

错误:

java.lang.IllegalArgumentException: 'publisher' must not be null
    at org.springframework.util.Assert.notNull(Assert.java:201)
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    *__checkpoint ⇢ org.springframework.security.web.server.authorization.AuthorizationWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.authentication.logout.LogoutWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.ui.LogoutPageGeneratingWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.ui.LoginPageGeneratingWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.authentication.AuthenticationWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.authentication.AuthenticationWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.csrf.CsrfWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.csrf.CsrfWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ HTTP POST "/admin/tally" [ExceptionHandlingWebHandler]
Original Stack Trace:
        at org.springframework.util.Assert.notNull(Assert.java:201)
        at org.springframework.web.reactive.function.BodyInserters.fromPublisher(BodyInserters.java:182)
        at org.springframework.web.reactive.function.server.DefaultServerResponseBuilder.body(DefaultServerResponseBuilder.java:233)
        at my.company.app.handler.TallyHandler.lambda$1(TallyHandler.java:58)

我试图模拟tallyService的返回值,但测试没有在ServerResponse的主体中提取它。 我应该怎么做才能模拟那部分代码以返回正确的ServerResponse值?

我终于找到了这个问题的答案,我没有正确地模拟身体。

我正在这样做,

when(tallyService.createTally(req, exchange)).thenReturn(Mono.just(res));

当我应该这样做时,

when(tallyService.createTally(any(NewTallyRequest.class), any(ServerWebExchange.class)).thenReturn(Mono.just(res));

ServerResponse实体的主体没有被嘲笑,因此我面临返回空主体的错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM