/*** * * Copyright (c) 2009 Caelum - www.caelum.com.br/opensource All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. 2. Redistributions in * binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. 3. Neither the name of the * copyright holders nor the names of its contributors may be used to endorse or * promote products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package br.com.caelum.vraptor.http.iogi; import static java.util.Arrays.asList; import static java.util.Collections.enumeration; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.sameInstance; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.ResourceBundle; import java.util.Set; import org.junit.Test; import org.mockito.Mock; import br.com.caelum.iogi.parameters.Parameter; import br.com.caelum.iogi.parameters.Parameters; import br.com.caelum.iogi.reflection.Target; import br.com.caelum.vraptor.Result; import br.com.caelum.vraptor.core.Localization; import br.com.caelum.vraptor.core.SafeResourceBundle; import br.com.caelum.vraptor.http.ParametersProvider; import br.com.caelum.vraptor.http.ParametersProviderTest; import br.com.caelum.vraptor.resource.DefaultResourceMethod; import br.com.caelum.vraptor.resource.ResourceMethod; import br.com.caelum.vraptor.util.EmptyBundle; import br.com.caelum.vraptor.validator.Message; public class IogiParametersProviderTest extends ParametersProviderTest { private @Mock Localization mockLocalization; @Override protected ParametersProvider getProvider() { when(mockLocalization.getBundle()).thenReturn(new SafeResourceBundle(new EmptyBundle())); return new IogiParametersProvider(nameProvider, request, new VRaptorInstantiator(converters, new VRaptorDependencyProvider(container), mockLocalization, new VRaptorParameterNamesProvider(nameProvider), request)); } @Test public void returnsNullWhenInstantiatingAStringForWhichThereAreNoParameters() throws Exception { thereAreNoParameters(); final ResourceMethod method = string; Object[] params = provider.getParametersFor(method, errors, null); assertArrayEquals(new Object[] {null}, params); } @Test public void canInjectADependencyProvidedByVraptor() throws Exception { thereAreNoParameters(); ResourceMethod resourceMethod = DefaultResourceMethod.instanceFor(OtherResource.class, OtherResource.class.getDeclaredMethod("logic", NeedsMyResource.class)); final MyResource providedInstance = new MyResource(); when(container.canProvide(MyResource.class)).thenReturn(true); when(container.instanceFor(MyResource.class)).thenReturn(providedInstance); Object[] params = provider.getParametersFor(resourceMethod, errors, null); assertThat(((NeedsMyResource)params[0]).getMyResource(), is(sameInstance(providedInstance))); } //---------- The Following tests mock iogi to unit test the ParametersProvider impl. @Test public void willCreateAnIogiParameterForEachRequestParameterValue() throws Exception { ResourceMethod anyMethod = buyA; requestParameterIs(anyMethod, "name", "a", "b"); final InstantiatorWithErrors mockInstantiator = mock(InstantiatorWithErrors.class); final Parameters expectedParamters = new Parameters( Arrays.asList(new Parameter("name", "a"), new Parameter("name", "b"))); IogiParametersProvider iogiProvider = new IogiParametersProvider(nameProvider, request, mockInstantiator); iogiProvider.getParametersFor(anyMethod, errors, null); verify(mockInstantiator).instantiate(any(Target.class), eq(expectedParamters), eq(errors)); } @Test public void willCreateATargerForEachFormalParameterDeclaredByTheMethod() throws Exception { final ResourceMethod buyAHouse = buyA; requestParameterIs(buyAHouse, "house", ""); final InstantiatorWithErrors mockInstantiator = mock(InstantiatorWithErrors.class); IogiParametersProvider iogiProvider = new IogiParametersProvider(nameProvider, request, mockInstantiator); final Target<House> expectedTarget = Target.create(House.class, "house"); iogiProvider.getParametersFor(buyAHouse, errors, null); verify(mockInstantiator).instantiate(eq(expectedTarget), any(Parameters.class), eq(errors)); } @Test public void willAddValidationMessagesForConversionErrors() throws Exception { ResourceMethod setId = simple; requestParameterIs(setId, "id", "asdf"); getParameters(setId); assertThat(errors.size(), is(1)); } @Test public void inCaseOfConversionErrorsOnlyNullifyTheProblematicParameter() throws Exception { ResourceMethod setId = DefaultResourceMethod.instanceFor(House.class, House.class.getMethod("setCat", Cat.class)); requestParameterIs(setId, "cat.lols", "sad kitten"); Cat cat = getParameters(setId); assertThat(cat, is(notNullValue())); assertThat(cat.getLols(), is(nullValue())); } @Test public void isCapableOfDealingWithSets() throws Exception { when(nameProvider.parameterNamesFor(any(Method.class))).thenReturn(new String[]{"abc"}); ResourceMethod set = method("set", Set.class); requestParameterIs(set, "abc", "1", "2"); Set<Long> abc = getParameters(set); assertThat(abc, hasSize(2)); assertThat(abc, allOf(hasItem(1l), hasItem(2l))); } @Test public void isCapableOfDealingWithSetsOfObjects() throws Exception { when(nameProvider.parameterNamesFor(any(Method.class))).thenReturn(new String[]{"abc"}); ResourceMethod set = method("setOfObject", Set.class); requestParameterIs(set, "abc.x", "1"); Set<ABC> abc = getParameters(set); assertThat(abc, hasSize(1)); assertThat(abc.iterator().next().getX(), is(1l)); } @Test public void shouldInjectOnlyAttributesWithSameType() throws Exception { Object result = mock(Result.class); ResourceBundle emptyBundle = mock(ResourceBundle.class); ResourceMethod method = DefaultResourceMethod.instanceFor(OtherResource.class, OtherResource.class.getDeclaredMethod("logic", String.class)); when(request.getAttribute("result")).thenReturn(result); when(request.getParameterValues("result")).thenReturn(new String[] { "buggy" }); when(request.getParameterNames()).thenReturn(enumeration(asList("result"))); when(nameProvider.parameterNamesFor(method.getMethod())).thenReturn(new String[] { "result" }); List<Message> errors = new ArrayList<Message>(); Object[] out = provider.getParametersFor(method, errors, emptyBundle); assertThat(out[0], is(not(result))); } //---------- class OtherResource { void logic(NeedsMyResource param) { } void logic(String result) { } } static class NeedsMyResource { private final MyResource myResource; public NeedsMyResource(MyResource myResource) { this.myResource = myResource; } public MyResource getMyResource() { return myResource; } } }