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, ""));
}
}