/*** * Copyright (c) 2009 Caelum - wwyhiw.caelum.com.br/opensource * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package br.com.caelum.vraptor.interceptor; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.Mockito.anyString; import java.io.IOException; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.ResourceBundle; import net.vidageek.mirror.dsl.Mirror; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import br.com.caelum.vraptor.HeaderParam; import br.com.caelum.vraptor.InterceptionException; import br.com.caelum.vraptor.Validator; 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.MutableRequest; import br.com.caelum.vraptor.http.ParameterNameProvider; import br.com.caelum.vraptor.http.ParametersProvider; import br.com.caelum.vraptor.resource.DefaultResourceMethod; import br.com.caelum.vraptor.resource.ResourceMethod; import br.com.caelum.vraptor.validator.Message; import br.com.caelum.vraptor.validator.ValidationMessage; import br.com.caelum.vraptor.view.FlashScope; public class ParametersInstantiatorInterceptorTest { private @Mock MethodInfo params; private @Mock ParametersProvider parametersProvider; private @Mock ParameterNameProvider parameterNameProvider; private @Mock Validator validator; private @Mock Localization localization; private @Mock InterceptorStack stack; private @Mock ResourceBundle bundle; private @Mock MutableRequest request; private @Mock FlashScope flash; private List<Message> errors ; private ParametersInstantiatorInterceptor instantiator; private ResourceMethod method; private ResourceMethod otherMethod; @Before @SuppressWarnings("unchecked") public void setup() throws Exception { MockitoAnnotations.initMocks(this); when(localization.getBundle()).thenReturn(bundle); when(request.getParameterNames()).thenReturn(Collections.enumeration(Collections.EMPTY_LIST)); this.instantiator = new ParametersInstantiatorInterceptor(parametersProvider, parameterNameProvider, params, validator, localization, request, flash); this.errors = (List<Message>) new Mirror().on(instantiator).get().field("errors"); this.method = DefaultResourceMethod.instanceFor(Component.class, Component.class.getDeclaredMethod("method")); this.otherMethod = DefaultResourceMethod.instanceFor(Component.class, Component.class.getDeclaredMethod("otherMethod", int.class)); } class Component { void method() { } void otherMethod(int oneParam){ } } class HeaderParamComponent{ void method(@HeaderParam("X-MyApp-Password") String password) {} void otherMethod(@HeaderParam("X-MyApp-User") String user,@HeaderParam("X-MyApp-Password") String password, @HeaderParam("X-MyApp-Token") String token) {} } @Test public void shouldAcceptIfMethodHasParameters() { assertTrue(instantiator.accepts(otherMethod)); } @Test public void shouldNotAcceptIfMethodHasNoParameters() { assertFalse(instantiator.accepts(method)); } @Test public void shouldUseTheProvidedParameters() throws InterceptionException, IOException, NoSuchMethodException { Object[] values = new Object[] { new Object() }; when(parametersProvider.getParametersFor(method, errors, bundle)).thenReturn(values); instantiator.intercept(stack, method, null); verify(params).setParameters(values); verify(stack).next(method, null); verify(validator).addAll(Collections.<Message>emptyList()); } @Test public void shouldConvertArrayParametersToIndexParameters() throws Exception { when(request.getParameterNames()).thenReturn(Collections.enumeration(Arrays.asList("someParam[].id", "unrelatedParam"))); when(request.getParameterValues("someParam[].id")).thenReturn(new String[] {"one", "two", "three"}); instantiator.intercept(stack, method, null); verify(request).setParameter("someParam[0].id", "one"); verify(request).setParameter("someParam[1].id", "two"); verify(request).setParameter("someParam[2].id", "three"); } /** * Bug related */ @Test(expected=IllegalArgumentException.class) public void shouldThrowExceptionWhenThereIsAParameterContainingDotClass() throws Exception { when(request.getParameterNames()).thenReturn(Collections.enumeration(Arrays.asList("someParam.class.id", "unrelatedParam"))); when(request.getParameterValues("someParam.class.id")).thenReturn(new String[] {"whatever"}); instantiator.intercept(stack, method, null); } @Test public void shouldUseAndDiscardFlashParameters() throws InterceptionException, IOException, NoSuchMethodException { Object[] values = new Object[] { new Object() }; when(flash.consumeParameters(method)).thenReturn(values); instantiator.intercept(stack, method, null); verify(params).setParameters(values); verify(stack).next(method, null); verify(validator).addAll(Collections.<Message>emptyList()); verify(parametersProvider, never()).getParametersFor(method, errors, bundle); } @Test public void shouldValidateParameters() throws Exception { Object[] values = new Object[]{0}; when(parametersProvider.getParametersFor(otherMethod, errors, bundle)).thenAnswer(addErrorsToListAndReturn(values, "error1")); instantiator.intercept(stack, otherMethod, null); verify(validator).addAll(errors); verify(stack).next(otherMethod, null); verify(params).setParameters(values); } @Test(expected=RuntimeException.class) public void shouldThrowException() throws Exception { when(parametersProvider.getParametersFor(method, errors, bundle)).thenThrow(new RuntimeException()); instantiator.intercept(stack, method, null); } @Test public void shouldAddHeaderInformationToRequestWhenHeaderParamAnnotationIsPresent() throws Exception { Object[] values = new Object[] { new Object() }; Method method = HeaderParamComponent.class.getDeclaredMethod("method", String.class); ResourceMethod resourceMethod = DefaultResourceMethod.instanceFor(HeaderParamComponent.class, method); when(request.getHeader("X-MyApp-Password")).thenReturn("123"); when(parametersProvider.getParametersFor(resourceMethod, errors, bundle)).thenReturn(values); when(parameterNameProvider.parameterNamesFor(method)).thenReturn(new String[]{"password"}); instantiator.intercept(stack, resourceMethod, null); verify(request).setAttribute("password", "123"); verify(params).setParameters(values); verify(stack).next(resourceMethod, null); verify(validator).addAll(Collections.<Message>emptyList()); } @Test public void shouldAddHeaderInformationToRequestWhenHeaderParamAnnotationIsNotPresent() throws Exception { Object[] values = new Object[] { new Object() }; Method method = Component.class.getDeclaredMethod("method"); ResourceMethod resourceMethod = DefaultResourceMethod.instanceFor(Component.class, method); when(parametersProvider.getParametersFor(resourceMethod, errors, bundle)).thenReturn(values); when(parameterNameProvider.parameterNamesFor(method)).thenReturn(new String[]{"password"}); instantiator.intercept(stack, resourceMethod, null); verify(request, never()).setAttribute(anyString(), anyString()); verify(params).setParameters(values); verify(stack).next(resourceMethod, null); verify(validator).addAll(Collections.<Message>emptyList()); } @Test public void shouldAddVariousHeaderInformationsToRequestWhenHeaderParamAnnotationIsPresent() throws Exception { Object[] values = new Object[] { new Object() }; Method method = HeaderParamComponent.class.getDeclaredMethod("otherMethod", String.class, String.class, String.class); ResourceMethod resouceMethod = DefaultResourceMethod.instanceFor(HeaderParamComponent.class, method); when(request.getHeader("X-MyApp-User")).thenReturn("user"); when(request.getHeader("X-MyApp-Password")).thenReturn("123"); when(request.getHeader("X-MyApp-Token")).thenReturn("daek2321"); when(parametersProvider.getParametersFor(resouceMethod, errors, bundle)).thenReturn(values); when(parameterNameProvider.parameterNamesFor(method)).thenReturn(new String[]{"user", "password", "token"}); instantiator.intercept(stack, resouceMethod, null); verify(request).setAttribute("user", "user"); verify(request).setAttribute("password", "123"); verify(request).setAttribute("token", "daek2321"); verify(params).setParameters(values); verify(stack).next(resouceMethod, null); verify(validator).addAll(Collections.<Message>emptyList()); } private <T> Answer<T> addErrorsToListAndReturn(final T value, final String... messages) { return new Answer<T>() { public T answer(InvocationOnMock invocation) throws Throwable { for (String message : messages) { errors.add(new ValidationMessage(message, "test")); } return value; } }; } }