Polishing in data binding tests

See gh-32676
This commit is contained in:
rstoyanchev 2024-06-04 09:55:09 +01:00
parent 36b0702c0b
commit 398aae2b9a
4 changed files with 46 additions and 42 deletions

View File

@ -148,11 +148,17 @@ public class WebExchangeDataBinder extends WebDataBinder {
protected static void addBindValue(Map<String, Object> params, String key, List<?> values) {
if (!CollectionUtils.isEmpty(values)) {
values = values.stream()
.map(value -> value instanceof FormFieldPart formFieldPart ? formFieldPart.value() : value)
.toList();
params.put(key, values.size() == 1 ? values.get(0) : values);
if (values.size() == 1) {
params.put(key, adaptBindValue(values.get(0)));
}
else {
params.put(key, values.stream().map(WebExchangeDataBinder::adaptBindValue).toList());
}
}
}
private static Object adaptBindValue(Object value) {
return (value instanceof FormFieldPart part ? part.value() : value);
}

View File

@ -16,10 +16,11 @@
package org.springframework.web.reactive;
import java.lang.reflect.Method;
import jakarta.validation.Valid;
import org.junit.jupiter.api.Test;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.validation.Errors;
import org.springframework.validation.SmartValidator;
@ -27,7 +28,6 @@ import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpRequest;
import org.springframework.web.testfixture.method.ResolvableMethod;
import org.springframework.web.testfixture.server.MockServerWebExchange;
import static org.assertj.core.api.Assertions.assertThat;
@ -40,44 +40,37 @@ import static org.mockito.BDDMockito.when;
class BindingContextTests {
@Test
void jakartaValidatorExcludedWhenMethodValidationApplicable() {
void jakartaValidatorExcludedWhenMethodValidationApplicable() throws Exception {
BindingContext bindingContext = new BindingContext(null);
bindingContext.setMethodValidationApplicable(true);
MethodParameter parameter = ResolvableMethod.on(BindingContextTests.class)
.named("handle").build().annotPresent(Valid.class).arg();
Method method = getClass().getDeclaredMethod("handleValidObject", Foo.class);
ResolvableType targetType = ResolvableType.forMethodParameter(method, 0);
WebDataBinder dataBinder = bindingContext.createDataBinder(
MockServerWebExchange.from(MockServerHttpRequest.get("")), new Foo(), "foo",
ResolvableType.forMethodParameter(parameter));
WebDataBinder binder = bindingContext.createDataBinder(
MockServerWebExchange.from(MockServerHttpRequest.get("")), new Foo(), "foo", targetType);
Validator springValidator = mock(Validator.class);
when(springValidator.supports(Foo.class)).thenReturn(true);
dataBinder.addValidators(springValidator);
binder.addValidators(springValidator);
LocalValidatorFactoryBean beanValidator = new LocalValidatorFactoryBean();
beanValidator.afterPropertiesSet();
dataBinder.addValidators(beanValidator);
binder.addValidators(beanValidator);
WrappedBeanValidator wrappedBeanValidator = new WrappedBeanValidator(beanValidator);
dataBinder.addValidators(wrappedBeanValidator);
binder.addValidators(wrappedBeanValidator);
assertThat(dataBinder.getValidatorsToApply()).containsExactly(springValidator);
assertThat(binder.getValidatorsToApply()).containsExactly(springValidator);
}
@SuppressWarnings("unused")
private void handle(@Valid Foo foo) {
private void handleValidObject(@Valid Foo foo) {
}
private static class WrappedBeanValidator implements SmartValidator {
private final jakarta.validation.Validator validator;
private WrappedBeanValidator(jakarta.validation.Validator validator) {
this.validator = validator;
}
private record WrappedBeanValidator(jakarta.validation.Validator validator) implements SmartValidator {
@Override
public boolean supports(Class<?> clazz) {
@ -100,6 +93,6 @@ class BindingContextTests {
}
private static class Foo {}
private static final class Foo {}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -81,24 +81,29 @@ public class ExtendedServletRequestDataBinder extends ServletRequestDataBinder {
protected void addBindValues(MutablePropertyValues mpvs, ServletRequest request) {
Map<String, String> uriVars = getUriVars(request);
if (uriVars != null) {
uriVars.forEach((name, value) -> {
if (mpvs.contains(name)) {
if (logger.isDebugEnabled()) {
logger.debug("URI variable '" + name + "' overridden by request bind value.");
}
}
else {
mpvs.addPropertyValue(name, value);
}
});
uriVars.forEach((name, value) -> addValueIfNotPresent(mpvs, "URI variable", name, value));
}
}
@SuppressWarnings("unchecked")
@Nullable
private static Map<String, String> getUriVars(ServletRequest request) {
String attr = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
return (Map<String, String>) request.getAttribute(attr);
return (Map<String, String>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
}
private static void addValueIfNotPresent(
MutablePropertyValues mpvs, String label, String name, @Nullable Object value) {
if (value != null) {
if (mpvs.contains(name)) {
if (logger.isDebugEnabled()) {
logger.debug(label + " '" + name + "' overridden by request bind value.");
}
}
else {
mpvs.addPropertyValue(name, value);
}
}
}

View File

@ -45,10 +45,10 @@ class ExtendedServletRequestDataBinderTests {
@Test
void createBinder() {
Map<String, String> uriTemplateVars = new HashMap<>();
uriTemplateVars.put("name", "nameValue");
uriTemplateVars.put("age", "25");
request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVars);
this.request.setAttribute(
HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE,
Map.of("name", "nameValue", "age", "25"));
TestBean target = new TestBean();
ServletRequestDataBinder binder = new ExtendedServletRequestDataBinder(target, "");