簡體   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