How to add run-time processing of @NotNull annotation
I was quite surprised to see that IntelliJ actually does runtime verification of @NotNull开发者_JS百科 within IDEA when running/debugging a unit test. Is it possible for me to add this same feature to my maven build? (What jars/jvm settings do I require?)
IDEA is using its own method of instrumenting bytecode to add such validations. For command line builds we provide javac2 Ant task that does the instrumentation (extends standard javac task). If you generate Ant build from IDEA, you will have an option to use javac2.
We don't provide similar Maven plug-in yet, but there is third-party version which may work for you (though, it seems to be a bit old).
I'd go the AOP way:
First of all you need a javax.validation compatible validator (Hibernate Validator is the reference implementation).
Now create an aspectj aspect that has a Validator instance and checks all method parameters for validation errors. Here is a quick version to get you started:
public aspect ValidationAspect {
private final Validator validator;
{
final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
pointcut serviceMethod() : execution(public * com.yourcompany**.*(..));
before() : serviceMethod(){
final Method method = (Method) thisJoinPoint.getTarget();
for(final Object arg : thisJoinPoint.getArgs()){
if(arg!=null) validateArg(arg,method);
}
}
private void validateArg(final Object arg, final Method method) {
final Set<ConstraintViolation<Object>> validationErrors = validator.validate(arg);
if(!validationErrors.isEmpty()){
final StringBuilder sb = new StringBuilder();
sb.append("Validation Errors in method ").append(method).append(":\n");
for (final ConstraintViolation<Object> constraintViolation : validationErrors) {
sb.append(" - ").append(constraintViolation.getMessage()).append("\n");
}
throw new RuntimeException(sb.toString());
}
}
}
Use the aspectj-maven-plugin to weave that aspect into your test and / or production code.
If you only want this functionality for testing, you might put the aspectj-plugin execution in a profile.
There is a maven plugin closely affiliated with the IntelliJ functionality, currently at https://github.com/osundblad/intellij-annotations-instrumenter-maven-plugin. It is discussed under the IDEA-31368 ticket first mentioned in CrazyCoder's answer.
You can do annotation validation in your JUnit tests.
import java.util.Set;
import javax.validation.ConstraintViolation;
import junit.framework.Assert;
import org.hibernate.validator.HibernateValidator;
import org.junit.Before;
import org.junit.Test;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
public class Temp {
private LocalValidatorFactoryBean localValidatorFactory;
@Before
public void setup() {
localValidatorFactory = new LocalValidatorFactoryBean();
localValidatorFactory.setProviderClass(HibernateValidator.class);
localValidatorFactory.afterPropertiesSet();
}
@Test
public void testLongNameWithInvalidCharCausesValidationError() {
final ProductModel productModel = new ProductModel();
productModel.setLongName("A long name with\t a Tab character");
Set<ConstraintViolation<ProductModel>> constraintViolations = localValidatorFactory.validate(productModel);
Assert.assertTrue("Expected validation error not found", constraintViolations.size() == 1);
}
}
If your poison is Spring, take a look at these Spring Unit Tests
精彩评论