Spring WebFlux API层单元测试返回404问题求助
Spring WebFlux + OpenAPI Generator 单元测试返回404问题
我基于Spring Boot 3.0学习Spring WebFlux,使用OpenAPI Generator构建Person API。手动测试应用时能得到预期结果,但API层的单元测试始终返回404状态码,修改过Context Configuration也无法解决问题,求帮助。
测试类
@WebFluxTest(controllers = {PersonApiController.class}) @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = {PersonMapperImpl.class, H2PersonRepository.class, PersonRepository.class}) @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) class PersonRouterTest { @MockBean private PersonService personService; @Autowired private WebTestClient client; @ParameterizedTest @CsvSource({"1234, Max Mustermann", "5678, Erika Musterfrau"}) void retrieve_a_name(String id, String name) { when(personService.getPersonDataByID(1234)).thenReturn(Mono.just(new PersonData(1234, "Max Mustermann"))); when(personService.getPersonDataByID(5678)).thenReturn(Mono.just(new PersonData(5678, "Erika Musterfrau"))); client.get() .uri(uriBuilder -> uriBuilder .path("/persons/{id}") .build(id)) .accept(MediaType.ALL) .exchange() .expectStatus().isOk() .expectHeader().contentType(MediaType.APPLICATION_JSON) .expectBody() .jsonPath("$.name").isEqualTo(name); } }
控制器类
@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2022-12-09T09:14:36.692713900+01:00[Europe/Vienna]") @Controller @RequestMapping("${openapi.openAPIDefinition.base-path:}") public class PersonApiController implements PersonApi { private final PersonApiDelegate delegate; public PersonApiController(@Autowired(required = false) PersonApiDelegate delegate) { this.delegate = Optional.ofNullable(delegate).orElse(new PersonApiDelegate() {}); } @Override public PersonApiDelegate getDelegate() { return delegate; } }
API接口
@Tag( name = "Person", description = "the Person API" ) public interface PersonApi { default PersonApiDelegate getDelegate() { return new PersonApiDelegate() { }; } @Operation( operationId = "findPersonById", summary = "Find Person by ID", tags = {"Person"}, responses = {@ApiResponse( responseCode = "200", description = "successful operation", content = {@Content( mediaType = "application/json", schema = @Schema( implementation = PersonData.class ) )} )} ) @RequestMapping( method = {RequestMethod.GET}, value = {"/persons/{id}"}, produces = {"application/json"} ) default Mono<ResponseEntity<PersonData>> findPersonById(@Parameter(name = "id",description = "Person ID",required = true) @PathVariable("id") Integer id, @Parameter(hidden = true) final ServerWebExchange exchange) { return this.getDelegate().findPersonById(id, exchange); } @Operation( operationId = "savePerson", summary = "Creates a new Person", tags = {"Person"}, responses = {@ApiResponse( responseCode = "200", description = "successful operatoin", content = {@Content( mediaType = "application/json", schema = @Schema( implementation = PersonData.class ) )} )} ) @RequestMapping( method = {RequestMethod.POST}, value = {"/persons"}, produces = {"application/json"}, consumes = {"application/json"} ) default Mono<ResponseEntity<PersonData>> savePerson(@Parameter(name = "PersonData",description = "") @RequestBody(required = false) Mono<PersonData> personData, @Parameter(hidden = true) final ServerWebExchange exchange) { return this.getDelegate().savePerson(personData, exchange); } }
Delegate实现类
@Service public class PersonDelegateImpl implements PersonApiDelegate { public static final Mono<ResponseEntity<?>> RESPONSE_ENTITY_MONO = Mono.just(ResponseEntity.notFound().build()); private final PersonService service; private final PersonMapper mapper; public PersonDelegateImpl(PersonService service, PersonMapper mapper) { this.service = service; this.mapper = mapper; } public static <T> Mono<ResponseEntity<T>> toResponseEntity(Mono<T> mono) { return mono.flatMap(t -> Mono.just(ResponseEntity.ok(t))) .onErrorResume(t -> Mono.just(ResponseEntity.internalServerError().build())); } @Override public Mono<ResponseEntity<PersonData>> findPersonById(Integer id, ServerWebExchange exchange) { Mono<com.ebcont.talenttoolbackend.person.PersonData> personDataByID = service.getPersonDataByID(id); return toResponseEntity(personDataByID.map(mapper::map)); } @Override public Mono<ResponseEntity<PersonData>> savePerson(Mono<PersonData> personData, ServerWebExchange exchange) { return PersonApiDelegate.super.savePerson(personData, exchange); }
测试报错信息
< 404 NOT_FOUND Not Found < Content-Type: [application/json] < Content-Length: [139] {"timestamp":"2022-12-09T08:45:41.278+00:00","path":"/persons/1234","status":404,"error":"Not Found","message":null,"requestId":"4805b8b8"}
内容的提问来源于stack exchange,提问作者Christoph Kronberger
相关产品推荐
相关产品推荐

