package br.com.caelum.vraptor.validator;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.Locale;
import javax.validation.MessageInterpolator;
import javax.validation.Valid;
import javax.validation.ValidatorFactory;
import javax.validation.constraints.NotNull;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import br.com.caelum.vraptor.Validator;
import br.com.caelum.vraptor.core.DefaultMethodInfo;
import br.com.caelum.vraptor.core.InterceptorStack;
import br.com.caelum.vraptor.core.Localization;
import br.com.caelum.vraptor.core.MethodInfo;
import br.com.caelum.vraptor.http.ParameterNameProvider;
import br.com.caelum.vraptor.http.ParanamerNameProvider;
import br.com.caelum.vraptor.ioc.Container;
import br.com.caelum.vraptor.proxy.InstanceCreator;
import br.com.caelum.vraptor.proxy.ObjenesisInstanceCreator;
import br.com.caelum.vraptor.resource.DefaultResourceMethod;
import br.com.caelum.vraptor.resource.ResourceMethod;
import br.com.caelum.vraptor.util.test.MockValidator;
/**
* Test method validator feature.
*
* @author Otávio Scherer Garcia
* @since 3.5
*/
public class MethodValidatorTest {
@Mock private Localization l10n;
@Mock private InterceptorStack stack;
@Mock private Container container;
private MethodValidatorInterceptor interceptor;
private ParameterNameProvider provider;
private Validator validator;
private ValidatorFactory factory;
private MessageInterpolator interpolator;
private ResourceMethod withConstraint;
private ResourceMethod withTwoConstraints;
private ResourceMethod withoutConstraint;
private ResourceMethod cascadeConstraint;
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
Locale.setDefault(Locale.ENGLISH);
provider = new ParanamerNameProvider();
doReturn(false).when(container).canProvide(any(Class.class));
doReturn(new ObjenesisInstanceCreator()).when(container).instanceFor(InstanceCreator.class);
DIConstraintValidatorFactory constraintValidatorFactory = new DIConstraintValidatorFactory(container);
MethodValidatorFactoryCreator methodValidatorCreator = new MethodValidatorFactoryCreator(provider, constraintValidatorFactory);
methodValidatorCreator.buildFactory();
factory = methodValidatorCreator.getInstance();
MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory();
interpolatorFactory.createInterpolator();
interpolator = interpolatorFactory.getInstance();
ValidatorFactoryCreator creator = new ValidatorFactoryCreator(interpolator);
creator.buildFactory();
validator = new MockValidator();
withConstraint = DefaultResourceMethod.instanceFor(MyController.class, MyController.class.getMethod("withConstraint", String.class));
withTwoConstraints = DefaultResourceMethod.instanceFor(MyController.class, MyController.class.getMethod("withTwoConstraints", String.class, Customer.class));
withoutConstraint = DefaultResourceMethod.instanceFor(MyController.class, MyController.class.getMethod("withoutConstraint", String.class));
cascadeConstraint = DefaultResourceMethod.instanceFor(MyController.class, MyController.class.getMethod("cascadeConstraint", Customer.class));
}
@Test
public void shouldAcceptIfMethodHasConstraint() {
interceptor = new MethodValidatorInterceptor(null, null, null, null, factory.getValidator(), null);
assertThat(interceptor.accepts(withConstraint), is(true));
interceptor = new MethodValidatorInterceptor(null, null, null, null, factory.getValidator(), null);
assertThat(interceptor.accepts(withTwoConstraints), is(true));
interceptor = new MethodValidatorInterceptor(null, null, null, null, factory.getValidator(), null);
assertThat(interceptor.accepts(cascadeConstraint), is(true));
}
@Test
public void shouldNotAcceptIfMethodHasConstraint() {
interceptor = new MethodValidatorInterceptor(null, null, null, null, factory.getValidator(), null);
assertThat(interceptor.accepts(withoutConstraint), is(false));
}
@Test
public void shouldValidateMethodWithConstraint()
throws Exception {
MethodInfo info = new DefaultMethodInfo();
info.setParameters(new Object[] { null });
info.setResourceMethod(withConstraint);
interceptor = new MethodValidatorInterceptor(l10n, interpolator, validator, info, factory.getValidator(), provider);
when(l10n.getLocale()).thenReturn(new Locale("pt", "br"));
MyController controller = new MyController();
interceptor.intercept(stack, info.getResourceMethod(), controller);
assertThat(validator.getErrors(), hasSize(1));
assertThat(validator.getErrors().get(0).getCategory(), is("withConstraint.email"));
}
@Test
public void shouldUseDefaultLocale()
throws Exception {
MethodInfo info = new DefaultMethodInfo();
info.setParameters(new Object[] { null });
info.setResourceMethod(withConstraint);
interceptor = new MethodValidatorInterceptor(l10n, interpolator, validator, info, factory.getValidator(), provider);
MyController controller = new MyController();
interceptor.intercept(stack, info.getResourceMethod(), controller);
assertThat(validator.getErrors(), hasSize(1));
assertThat(validator.getErrors().get(0).getCategory(), is("withConstraint.email"));
assertThat(validator.getErrors().get(0).getMessage(), is("may not be null"));
}
@Test
public void shouldValidateMethodWithTwoConstraints()
throws Exception {
MethodInfo info = new DefaultMethodInfo();
info.setParameters(new Object[] { null, new Customer(null, null) });
info.setResourceMethod(withTwoConstraints);
interceptor = new MethodValidatorInterceptor(l10n, interpolator, validator, info, factory.getValidator(), provider);
when(l10n.getLocale()).thenReturn(new Locale("pt", "br"));
MyController controller = new MyController();
interceptor.intercept(stack, info.getResourceMethod(), controller);
String messages = validator.getErrors().toString();
assertThat(validator.getErrors(), hasSize(3));
assertThat(messages, containsString("não pode ser nulo"));
assertThat(messages, containsString("withTwoConstraints.name"));
assertThat(messages, containsString("withTwoConstraints.customer.name"));
assertThat(messages, containsString("withTwoConstraints.customer.id"));
}
/**
* Customer for using in bean validator tests.
*/
public class Customer {
@NotNull public Integer id;
@NotNull public String name;
public Customer(Integer id, String name) {
this.id = id;
this.name = name;
}
}
public class MyController {
public void withConstraint(@NotNull String email) {
}
public void withTwoConstraints(@NotNull String name, @Valid Customer customer) {
}
public void withoutConstraint(@Foo String foo) {
}
public void cascadeConstraint(@Valid Customer customer) {
}
}
@Target(value = { PARAMETER })
@Retention(value = RUNTIME)
@Documented
public @interface Foo {
}
}