/***
* Copyright (c) 2009 Caelum - www.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.observer;
import static org.junit.Assert.assertEquals;
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 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.controller.ControllerMethod;
import br.com.caelum.vraptor.controller.DefaultControllerMethod;
import br.com.caelum.vraptor.core.MethodInfo;
import br.com.caelum.vraptor.events.InterceptorsReady;
import br.com.caelum.vraptor.http.ParanamerNameProvider;
import br.com.caelum.vraptor.ioc.Container;
import br.com.caelum.vraptor.serialization.Deserializer;
import br.com.caelum.vraptor.serialization.Deserializers;
import br.com.caelum.vraptor.view.Status;
public class DeserializingObserverTest {
private DeserializingObserver observer;
private ControllerMethod consumeXml;
private ControllerMethod doesntConsume;
private MethodInfo methodInfo;
@Mock private HttpServletRequest request;
@Mock Deserializers deserializers;
@Mock Container container;
@Mock private Status status;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
methodInfo = new MethodInfo(new ParanamerNameProvider());
observer = new DeserializingObserver(deserializers, container);
consumeXml = new DefaultControllerMethod(null, DummyResource.class.getDeclaredMethod("consumeXml", String.class, String.class));
doesntConsume = new DefaultControllerMethod(null, DummyResource.class.getDeclaredMethod("doesntConsume"));
}
static class DummyResource {
@Consumes("application/xml")
public void consumeXml(String a, String b) {}
@Consumes()
public void consumesAnything(String a, String b) {}
public void doesntConsume() {}
}
@Test
public void shouldOnlyAcceptMethodsWithConsumesAnnotation() throws Exception {
observer.deserializes(new InterceptorsReady(doesntConsume), request, methodInfo, status);
verifyZeroInteractions(request);
}
@Test
public void willSetHttpStatusCode415IfTheControllerMethodDoesNotSupportTheGivenMediaTypes() throws Exception {
when(request.getContentType()).thenReturn("image/jpeg");
observer.deserializes(new InterceptorsReady(consumeXml), request, methodInfo, status);
verify(status).unsupportedMediaType("Request with media type [image/jpeg]. Expecting one of [application/xml].");
}
@Test
public void willSetHttpStatusCode415IfThereIsNoDeserializerButIsAccepted() throws Exception {
when(request.getContentType()).thenReturn("application/xml");
when(deserializers.deserializerFor("application/xml", container)).thenReturn(null);
observer.deserializes(new InterceptorsReady(consumeXml), request, methodInfo, status);
verify(status).unsupportedMediaType("Unable to handle media type [application/xml]: no deserializer found.");
}
@Test
public void willSetMethodParametersWithDeserializationAndContinueStackAfterDeserialization() throws Exception {
final Deserializer deserializer = mock(Deserializer.class);
methodInfo.setControllerMethod(consumeXml);
when(request.getContentType()).thenReturn("application/xml");
when(deserializer.deserialize(null, consumeXml)).thenReturn(new Object[] {"abc", "def"});
when(deserializers.deserializerFor("application/xml", container)).thenReturn(deserializer);
observer.deserializes(new InterceptorsReady(consumeXml), request, methodInfo, status);
assertEquals(methodInfo.getValuedParameters()[0].getValue(), "abc");
assertEquals(methodInfo.getValuedParameters()[1].getValue(), "def");
}
@Test
public void willSetMethodParametersWithDeserializationEvenIfTheContentTypeHasCharsetDeclaration() throws Exception {
final Deserializer deserializer = mock(Deserializer.class);
methodInfo.setControllerMethod(consumeXml);
when(request.getContentType()).thenReturn("application/xml; charset=UTF-8");
when(deserializer.deserialize(null, consumeXml)).thenReturn(new Object[] {"abc", "def"});
when(deserializers.deserializerFor("application/xml", container)).thenReturn(deserializer);
observer.deserializes(new InterceptorsReady(consumeXml), request, methodInfo, status);
assertEquals(methodInfo.getValuedParameters()[0].getValue(), "abc");
assertEquals(methodInfo.getValuedParameters()[1].getValue(), "def");
}
@Test
public void willDeserializeForAnyContentTypeIfPossible() throws Exception {
final ControllerMethod consumesAnything = new DefaultControllerMethod(null,
DummyResource.class.getDeclaredMethod("consumesAnything", String.class, String.class));
when(request.getContentType()).thenReturn("application/xml");
methodInfo.setControllerMethod(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);
observer.deserializes(new InterceptorsReady(consumesAnything), request, methodInfo, status);
assertEquals(methodInfo.getValuedParameters()[0].getValue(), "abc");
assertEquals(methodInfo.getValuedParameters()[1].getValue(), "def");
}
@Test
public void shouldNotDeserializeIfHasNoContentType() throws Exception {
final ControllerMethod consumesAnything = new DefaultControllerMethod(null, DummyResource.class.getDeclaredMethod("consumesAnything", String.class, String.class));
when(request.getContentType()).thenReturn(null);
methodInfo.setControllerMethod(consumesAnything);
observer.deserializes(new InterceptorsReady(consumesAnything), request, methodInfo, status);
assertEquals(methodInfo.getValuedParameters()[0].getValue(), null);
assertEquals(methodInfo.getValuedParameters()[1].getValue(), null);
}
@Test
public void willSetOnlyNonNullParameters() throws Exception {
final Deserializer deserializer = mock(Deserializer.class);
methodInfo.setControllerMethod(consumeXml);
methodInfo.getValuedParameters()[0].setValue("original1");
methodInfo.getValuedParameters()[1].setValue("original2");
when(request.getContentType()).thenReturn("application/xml");
when(deserializer.deserialize(null, consumeXml)).thenReturn(new Object[] {null, "deserialized"});
when(deserializers.deserializerFor("application/xml", container)).thenReturn(deserializer);
observer.deserializes(new InterceptorsReady(consumeXml), request, methodInfo, status);
assertEquals(methodInfo.getValuedParameters()[0].getValue(), "original1");
assertEquals(methodInfo.getValuedParameters()[1].getValue(), "deserialized");
}
}