Функция фильтра обработчика макета выдает нулевую ошибку сопоставления в тестахJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Функция фильтра обработчика макета выдает нулевую ошибку сопоставления в тестах

Сообщение Anonymous »

Я пытаюсь имитировать реализацию HandlerFilterFunction фильтра, прикрепленного к RouterFunction, который имеет вложенные пути, чтобы тестовые пути вызывали правильную функцию для обработки запросов. Но в тесте я получаю исключение с нулевым указателем, похоже, что макеты не вызываются.
Я определил функцию Router следующим образом:

Код: Выделить всё

@Slf4j
@Configuration
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class FormRouter {
private final XFabricCorrelationHeaderFilter xFabricCorrelationHeaderFilter;
private final ValidFormFilter validFormFilter;
private final FormHandler formHandler;
private final TabHandler tabHandler;
private final BlockHandler blockHandler;

@Setter(onMethod_ = {@Value("${form.url:/forms}")})
String serviceBaseURL;

@Bean
@FormRouterApiDocs
public RouterFunction formRoutes() {
return RouterFunctions.route()
.path(serviceBaseURL + "/{formId}", builder ->
builder.nest(accept(APPLICATION_JSON), nestedBuilder ->
nestedBuilder.path("/tabs", tabBuilder ->
tabBuilder.nest(accept(APPLICATION_JSON), nestedTabBuilder ->
nestedTabBuilder.path("/{tabId}/blocks", blocksHandlerBuilder ->
blocksHandlerBuilder.GET(blockHandler::getBlocks)
.PUT(blockHandler::postBlock))
.PUT(tabHandler::postTab)
.GET(tabHandler::getTabs)))
.GET(formHandler::getFormWithFormId)
.PUT(formHandler::putForm)
.DELETE(formHandler::deleteForm)
.filter(validFormFilter)))
.path(serviceBaseURL, b ->
b.nest(accept(APPLICATION_JSON), nestedBuilder ->
nestedBuilder.POST(formHandler::postForm)
.GET(formHandler::getFormList)))
.filter(xFabricCorrelationHeaderFilter)
.build();
}
}
Фильтр определяется следующим образом

Код: Выделить всё

@Slf4j
@Component
@RequiredArgsConstructor
public class ValidFormFilter implements HandlerFilterFunction {

private final FormService formService;

@Override
public @NonNull Mono filter(ServerRequest request, @NonNull HandlerFunction next) {
HttpMethod method = request.method();
String path = request.path();
if (method == HttpMethod.PUT || method == HttpMethod.PATCH || method == HttpMethod.GET || method == HttpMethod.DELETE) {
XFabricCorrelation xFabricCorrelation = XFabricCorrelationWebflux.fromServerRequest(request);
String formId = request.pathVariable("formId");
return formService.lookFormform(blah)
.doOnError(blah blah)
.flatMap(form -> add form as request attribute and return request)
.flatMap(next::handle)
.log(this.getClass().getName(), Level.FINE);
}
return next.handle(request);
}
}
а затем FormHandler

Код: Выделить всё

@Slf4j
@Component
@RequiredArgsConstructor
public class FormHandler {
... // dependencies

public Mono getFormWithFormId(ServerRequest serverRequest){
// do stuff and return response
}
Я хочу имитировать фильтр, так как хочу убедиться, что маршрут /forms/{formId}/tabs не соответствует /forms/{formId}< /code>, а также задокументировать это поведение для других разработчиков. Вот тестовый код

Код: Выделить всё

@Slf4j
@SpringJUnitConfig({FormRouter.class, CorrelationHeaderFilter.class, CommonHeaderInfo.class})
@TestPropertySource(inheritLocations = false, locations = {"classpath:webflux-test.properties"})
@DisplayName("Form API Routes")
@MockBeans({@MockBean(FormHandler.class), @MockBean(TabHandler.class), @MockBean(BlockHandler.class), @MockBean(ValidFormFilter.class)})
class FormRoutesTest {
...
@Autowired
FormRouter formRouter;

@Autowired
FormHandler handler;
@Autowired
TabHandler tabHandler;
@Autowired
BlockHandler blockHandler;
@Autowired
ValidFormFilter formFilter;

WebTestClient webTestClient;
Form form;

@BeforeEach
void setUp() {
fabricHeader = String.join(":", realmId, accountId, workspaceId);
webTestClient = WebTestClient.bindToRouterFunction(formRouter.formRoutes()).configureClient().baseUrl(formRouter.serviceBaseURL).build();
log.debug("Registered Web Client on URL {}", formRouter.serviceBaseURL);
form = FormTestData.Given.aForm("1", realmId, accountId, workspaceId);
log.debug("Registered Form Service Mocks");
}

...

@Test
@DisplayName("THEN invokes getting form by Id")
void testGetFormWithFormIdWhenValidRequestHeader() {
when(handler.getFormWithFormId(any(ServerRequest.class))).thenReturn(ServerResponse.ok().build());
when(formFilter.filter(any(ServerRequest.class), any()))
.thenAnswer(invocation -> {
ServerRequest request = invocation.getArgument(0);
//                        HandlerFunction next = invocation.getArgument(1);
//                        // Simulate calling next.handle(request) in the filter
//                        return next.handle(request);
return handler.getFormWithFormId(request);
});

webTestClient.get()
.uri(uriBuilder -> uriBuilder.path("/{formId}").build(form.getFormId()))
.headers(httpHeaders -> httpHeaders.add(fabricAuthHeader, fabricHeader))
.exchange()
.expectStatus().isOk();

verify(formFilter).filter(any(ServerRequest.class), any());
verify(handler).getFormWithFormId(any(ServerRequest.class));
verifyNoMoreInteractions(handler);
}
}
Как видите, я пробовал и то, и другое: возвращая next.handle или напрямую вызывая метод formHandler, но в обоих случаях получаю ошибку

Код: Выделить всё

2024-10-21 14:51:17 ERROR [parallel-4] HttpWebHandlerAdapter.handleUnresolvedError:293 - [36ac6c0e] 500 Server Error for HTTP GET "/forms/1"
java.lang.NullPointerException: The mapper [org.springframework.web.reactive.function.server.RouterFunctions$FilteredRouterFunction$$Lambda$795/0x00000008005ab0b0] returned a null value.
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:108) ~[reactor-core-3.4.31.jar:3.4.31]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
*__checkpoint ⇢ HTTP GET "/forms/1" [ExceptionHandlingWebHandler]
Обратите внимание, что FormHandler не реализует HandlerFunction Я вызываю методы компонента напрямую. Действительный фильтр формы просто проверяет, существует ли форма и терпит неудачу, или вызывает next.handle(request)

Подробнее здесь: https://stackoverflow.com/questions/791 ... r-in-tests
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»