21
21
import jakarta .validation .Validator ;
22
22
import jakarta .validation .constraints .Min ;
23
23
import org .hibernate .validator .HibernateValidator ;
24
- import org .junit .jupiter .api .Assertions ;
25
24
import org .junit .jupiter .api .Test ;
26
25
27
26
import org .springframework .boot .test .context .FilteredClassLoader ;
30
29
import org .springframework .context .annotation .Bean ;
31
30
import org .springframework .context .annotation .Configuration ;
32
31
import org .springframework .core .io .ClassPathResource ;
32
+ import org .springframework .validation .Errors ;
33
33
import org .springframework .validation .MapBindingResult ;
34
+ import org .springframework .validation .SmartValidator ;
34
35
import org .springframework .validation .beanvalidation .LocalValidatorFactoryBean ;
35
36
36
37
import static org .assertj .core .api .Assertions .assertThat ;
38
+ import static org .assertj .core .api .Assertions .assertThatRuntimeException ;
37
39
import static org .mockito .ArgumentMatchers .any ;
38
40
import static org .mockito .BDDMockito .then ;
39
41
import static org .mockito .Mockito .mock ;
@@ -95,11 +97,26 @@ void wrapperWhenValidationProviderNotPresentShouldNotThrowException() {
95
97
}
96
98
97
99
@ Test
98
- void unwrapValidatorInstanceOfJakartaTypeAndExceptionThrownWhenTypeNotSupported () {
100
+ void unwrapToJakartaValidatorShouldReturnJakartaValidator () {
99
101
this .contextRunner .withUserConfiguration (LocalValidatorFactoryBeanConfig .class ).run ((context ) -> {
100
102
ValidatorAdapter wrapper = context .getBean (ValidatorAdapter .class );
101
103
assertThat (wrapper .unwrap (Validator .class )).isInstanceOf (Validator .class );
102
- Assertions .assertThrows (IllegalArgumentException .class , () -> wrapper .unwrap (HibernateValidator .class ));
104
+ });
105
+ }
106
+
107
+ @ Test
108
+ void whenJakartaValidatorIsWrappedMultipleTimesUnwrapToJakartaValidatorShouldReturnJakartaValidator () {
109
+ this .contextRunner .withUserConfiguration (DoubleWrappedConfig .class ).run ((context ) -> {
110
+ ValidatorAdapter wrapper = context .getBean (ValidatorAdapter .class );
111
+ assertThat (wrapper .unwrap (Validator .class )).isInstanceOf (Validator .class );
112
+ });
113
+ }
114
+
115
+ @ Test
116
+ void unwrapToUnsupportedTypeShouldThrow () {
117
+ this .contextRunner .withUserConfiguration (LocalValidatorFactoryBeanConfig .class ).run ((context ) -> {
118
+ ValidatorAdapter wrapper = context .getBean (ValidatorAdapter .class );
119
+ assertThatRuntimeException ().isThrownBy (() -> wrapper .unwrap (HibernateValidator .class ));
103
120
});
104
121
}
105
122
@@ -118,6 +135,55 @@ ValidatorAdapter wrapper(LocalValidatorFactoryBean validator) {
118
135
119
136
}
120
137
138
+ @ Configuration (proxyBeanMethods = false )
139
+ static class DoubleWrappedConfig {
140
+
141
+ @ Bean
142
+ LocalValidatorFactoryBean validator () {
143
+ return new LocalValidatorFactoryBean ();
144
+ }
145
+
146
+ @ Bean
147
+ ValidatorAdapter wrapper (LocalValidatorFactoryBean validator ) {
148
+ return new ValidatorAdapter (new Wrapper (validator ), true );
149
+ }
150
+
151
+ static class Wrapper implements SmartValidator {
152
+
153
+ private final SmartValidator delegate ;
154
+
155
+ Wrapper (SmartValidator delegate ) {
156
+ this .delegate = delegate ;
157
+ }
158
+
159
+ @ Override
160
+ public boolean supports (Class <?> clazz ) {
161
+ return this .delegate .supports (clazz );
162
+ }
163
+
164
+ @ Override
165
+ public void validate (Object target , Errors errors ) {
166
+ this .delegate .validate (target , errors );
167
+ }
168
+
169
+ @ Override
170
+ public void validate (Object target , Errors errors , Object ... validationHints ) {
171
+ this .delegate .validate (target , errors , validationHints );
172
+ }
173
+
174
+ @ Override
175
+ @ SuppressWarnings ("unchecked" )
176
+ public <T > T unwrap (Class <T > type ) {
177
+ if (type .isInstance (this .delegate )) {
178
+ return (T ) this .delegate ;
179
+ }
180
+ return this .delegate .unwrap (type );
181
+ }
182
+
183
+ }
184
+
185
+ }
186
+
121
187
@ Configuration (proxyBeanMethods = false )
122
188
static class NonManagedBeanConfig {
123
189
0 commit comments