When a method with parameter validation is invoked, the proxy intercepts the call, performs parameter validation, and only then proceeds to the actual method execution. This mechanism relies on MethodValidationInterceptor
.
To properly test such validation logic, it’s important to use the Spring context so that proxies are applied. There are several approaches:
@SpringBootTest
class UserServiceValidationTest {
@Autowired
private UserService userService;
@Test
void shouldThrowValidationException() {
User invalidUser = new User(); // invalid object
assertThrows(ConstraintViolationException.class,
() -> userService.createUser(invalidUser, ""));
}
}
@TestConfiguration
@EnableConfigurationProperties
public class ValidationTestConfig {
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
@Bean
@Validated
public UserService userService() {
return new UserService();
}
}
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = ValidationTestConfig.class)
class UserServiceTest {
@Autowired
private UserService userService;
@Test
void shouldValidateParameters() {
assertThrows(ConstraintViolationException.class,
() -> userService.createUser(null, "invalid-email"));
}
}
class UserServiceManualProxyTest {
private UserService userService;
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(new UserService());
proxyFactory.addAdvice(new MethodValidationInterceptor(validator));
userService = (UserService) proxyFactory.getProxy();
}
@Test
void shouldValidateWithManualProxy() {
User invalidUser = new User();
assertThrows(ConstraintViolationException.class,
() -> userService.createUser(invalidUser, ""));
}
}