package br.com.caelum.vraptor.interceptor; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import br.com.caelum.vraptor.Consumes; import br.com.caelum.vraptor.InterceptionException; import br.com.caelum.vraptor.core.DefaultMethodInfo; import br.com.caelum.vraptor.core.InterceptorStack; import br.com.caelum.vraptor.core.MethodInfo; import br.com.caelum.vraptor.deserialization.Deserializer; import br.com.caelum.vraptor.deserialization.Deserializers; import br.com.caelum.vraptor.ioc.Container; import br.com.caelum.vraptor.resource.DefaultResourceMethod; import br.com.caelum.vraptor.view.Status; public class DeserializingInterceptorTest { private DeserializingInterceptor interceptor; private DefaultResourceMethod consumeXml; private DefaultResourceMethod doesntConsume; @Mock private HttpServletRequest request; @Mock private InterceptorStack stack; @Mock Deserializers deserializers; private MethodInfo methodInfo; @Mock Container container; @Mock private Status status; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); methodInfo = new DefaultMethodInfo(); interceptor = new DeserializingInterceptor(request, deserializers, methodInfo, container, status); consumeXml = new DefaultResourceMethod(null, DummyResource.class.getDeclaredMethod("consumeXml")); doesntConsume = new DefaultResourceMethod(null, DummyResource.class.getDeclaredMethod("doesntConsume")); } static class DummyResource { @Consumes("application/xml") public void consumeXml() {} @Consumes() public void consumesAnything() {} public void doesntConsume() {} } @Test public void shouldOnlyAcceptMethodsWithConsumesAnnotation() throws Exception { assertTrue(interceptor.accepts(consumeXml)); assertFalse(interceptor.accepts(doesntConsume)); } @Test public void willSetHttpStatusCode415IfTheResourceMethodDoesNotSupportTheGivenMediaTypes() throws Exception { when(request.getContentType()).thenReturn("image/jpeg"); interceptor.intercept(stack, consumeXml, null); verify(status).unsupportedMediaType("Request with media type [image/jpeg]. Expecting one of [application/xml]."); verifyZeroInteractions(stack); } @Test public void willSetHttpStatusCode415IfThereIsNoDeserializerButIsAccepted() throws Exception { when(request.getContentType()).thenReturn("application/xml"); when(deserializers.deserializerFor("application/xml", container)).thenReturn(null); interceptor.intercept(stack, consumeXml, null); verify(status).unsupportedMediaType("Unable to handle media type [application/xml]: no deserializer found."); verifyZeroInteractions(stack); } @Test public void willSetMethodParametersWithDeserializationAndContinueStackAfterDeserialization() { when(request.getContentType()).thenReturn("application/xml"); final Deserializer deserializer = mock(Deserializer.class); methodInfo.setParameters(new Object[2]); when(deserializer.deserialize(null, consumeXml)).thenReturn(new Object[] {"abc", "def"}); when(deserializers.deserializerFor("application/xml", container)).thenReturn(deserializer); interceptor.intercept(stack, consumeXml, null); assertEquals(methodInfo.getParameters()[0], "abc"); assertEquals(methodInfo.getParameters()[1], "def"); verify(stack).next(consumeXml, null); } @Test public void willSetMethodParametersWithDeserializationEvenIfTheContentTypeHasCharsetDeclaration() { when(request.getContentType()).thenReturn("application/xml; charset=UTF-8"); final Deserializer deserializer = mock(Deserializer.class); methodInfo.setParameters(new Object[2]); when(deserializer.deserialize(null, consumeXml)).thenReturn(new Object[] {"abc", "def"}); when(deserializers.deserializerFor("application/xml", container)).thenReturn(deserializer); interceptor.intercept(stack, consumeXml, null); assertEquals(methodInfo.getParameters()[0], "abc"); assertEquals(methodInfo.getParameters()[1], "def"); verify(stack).next(consumeXml, null); } @Test public void willDeserializeForAnyContentTypeIfPossible() throws Exception { when(request.getContentType()).thenReturn("application/xml"); methodInfo.setParameters(new Object[2]); final DefaultResourceMethod consumesAnything = new DefaultResourceMethod(null, DummyResource.class.getDeclaredMethod("consumesAnything")); final Deserializer deserializer = mock(Deserializer.class); when(deserializer.deserialize(null, consumesAnything)).thenReturn(new Object[] {"abc", "def"}); when(deserializers.deserializerFor("application/xml", container)).thenReturn(deserializer); interceptor.intercept(stack, consumesAnything, null); assertEquals(methodInfo.getParameters()[0], "abc"); assertEquals(methodInfo.getParameters()[1], "def"); verify(stack).next(consumesAnything, null); } @Test public void shouldNotDeserializeIfHasNoContentType() throws Exception { when(request.getContentType()).thenReturn(null); methodInfo.setParameters(new Object[2]); final DefaultResourceMethod consumesAnything = new DefaultResourceMethod(null, DummyResource.class.getDeclaredMethod("consumesAnything")); interceptor.intercept(stack, consumesAnything, null); assertEquals(methodInfo.getParameters()[0], null); assertEquals(methodInfo.getParameters()[1], null); verify(stack).next(consumesAnything, null); } @Test public void willSetOnlyNonNullParameters() throws Exception { when(request.getContentType()).thenReturn("application/xml"); final Deserializer deserializer = mock(Deserializer.class); methodInfo.setParameters(new Object[] {"original1", "original2"}); when(deserializer.deserialize(null, consumeXml)).thenReturn(new Object[] {null, "deserialized"}); when(deserializers.deserializerFor("application/xml", container)).thenReturn(deserializer); interceptor.intercept(stack, consumeXml, null); assertEquals(methodInfo.getParameters()[0], "original1"); assertEquals(methodInfo.getParameters()[1], "deserialized"); verify(stack).next(consumeXml, null); } @Test(expected = InterceptionException.class) public void shouldThrowInterceptionExceptionIfAnIOExceptionOccurs() throws Exception { when(request.getInputStream()).thenThrow(new IOException()); when(request.getContentType()).thenReturn("application/xml"); final Deserializer deserializer = mock(Deserializer.class); when(deserializers.deserializerFor("application/xml", container)).thenReturn(deserializer); interceptor.intercept(stack, consumeXml, null); } }