package br.com.caelum.vraptor.deserialization; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.io.ByteArrayInputStream; import java.io.InputStream; import org.junit.Before; import org.junit.Test; import com.thoughtworks.xstream.annotations.XStreamAlias; import br.com.caelum.vraptor.http.ParameterNameProvider; import br.com.caelum.vraptor.interceptor.DefaultTypeNameExtractor; import br.com.caelum.vraptor.interceptor.TypeNameExtractor; import br.com.caelum.vraptor.resource.DefaultResourceClass; import br.com.caelum.vraptor.resource.DefaultResourceMethod; import br.com.caelum.vraptor.resource.ResourceClass; import br.com.caelum.vraptor.resource.ResourceMethod; import br.com.caelum.vraptor.serialization.xstream.XStreamBuilderImpl; public class JsonDeserializerTest { private JsonDeserializer deserializer; private ParameterNameProvider provider; private TypeNameExtractor extractor; private ResourceMethod meow; private ResourceMethod roll; private ResourceMethod jump; private ResourceMethod sleep; private ResourceMethod annotated; @Before public void setUp() throws Exception { provider = mock(ParameterNameProvider.class); extractor = new DefaultTypeNameExtractor(); deserializer = new JsonDeserializer(provider, extractor, XStreamBuilderImpl.cleanInstance()); ResourceClass resourceClass = new DefaultResourceClass(CatController.class); meow = new DefaultResourceMethod(resourceClass, CatController.class.getDeclaredMethod("meow")); roll = new DefaultResourceMethod(resourceClass, CatController.class.getDeclaredMethod("roll", Cat.class)); jump = new DefaultResourceMethod(resourceClass, CatController.class.getDeclaredMethod("jump", Cat.class, Integer.class)); sleep = new DefaultResourceMethod(resourceClass, CatController.class.getDeclaredMethod("sleep", Integer.class, Cat.class)); annotated = new DefaultResourceMethod(resourceClass, CatController.class.getDeclaredMethod("annotated", CatWithAnnotations.class)); } @XStreamAlias("catAnnotated") static class CatWithAnnotations { @XStreamAlias("nameAnnotated") private String name; @XStreamAlias("ageAnnotated") private Integer age; } static class Cat { private String name; private Integer age; } static class CatController { public void meow() { } public void roll(Cat cat) { } public void jump(Cat cat, Integer times) { } public void sleep(Integer hours, Cat cat) { } public void annotated(CatWithAnnotations cat){ } } @Test(expected=IllegalArgumentException.class) public void shouldNotAcceptMethodsWithoutArguments() throws Exception { deserializer.deserialize(new ByteArrayInputStream(new byte[0]), meow); } @Test public void shouldBeAbleToDeserializeACat() throws Exception { InputStream stream = new ByteArrayInputStream("{\"cat\":{\"name\": \"Samantha\", \"age\": 2}}".getBytes()); when(provider.parameterNamesFor(roll.getMethod())).thenReturn(new String[] {"cat"}); Object[] deserialized = deserializer.deserialize(stream, roll); assertThat(deserialized.length, is(1)); assertThat(deserialized[0], is(instanceOf(Cat.class))); Cat cat = (Cat) deserialized[0]; assertThat(cat.name, is("Samantha")); assertThat(cat.age, is(2)); } @Test public void shouldBeAbleToDeserializeACatWhenMethodHasMoreThanOneArgument() throws Exception { InputStream stream = new ByteArrayInputStream("{\"cat\":{\"name\": \"Zulu\", \"age\": 1}}".getBytes()); when(provider.parameterNamesFor(jump.getMethod())).thenReturn(new String[] {"cat", "times"}); Object[] deserialized = deserializer.deserialize(stream, jump); assertThat(deserialized.length, is(2)); assertThat(deserialized[0], is(instanceOf(Cat.class))); Cat cat = (Cat) deserialized[0]; assertThat(cat.name, is("Zulu")); assertThat(cat.age, is(1)); } @Test public void shouldBeAbleToDeserializeACatWhenMethodHasMoreThanOneArgumentAndTheXmlIsTheLastOne() throws Exception { InputStream stream = new ByteArrayInputStream("{\"cat\":{\"name\": \"Tigre\", \"age\": 3}}".getBytes()); when(provider.parameterNamesFor(sleep.getMethod())).thenReturn(new String[] {"hours", "cat"}); Object[] deserialized = deserializer.deserialize(stream, sleep); assertThat(deserialized.length, is(2)); assertThat(deserialized[1], is(instanceOf(Cat.class))); Cat cat = (Cat) deserialized[1]; assertThat(cat.name, is("Tigre")); assertThat(cat.age, is(3)); } @Test public void shouldBeAbleToDeserializeACatNamedDifferently() throws Exception { InputStream stream = new ByteArrayInputStream("{\"wrong\":{\"name\": \"Samantha\", \"age\": 2}}".getBytes()); when(provider.parameterNamesFor(roll.getMethod())).thenReturn(new String[] {"wrong"}); Object[] deserialized = deserializer.deserialize(stream, roll); assertThat(deserialized.length, is(1)); assertThat(deserialized[0], is(instanceOf(Cat.class))); Cat cat = (Cat) deserialized[0]; assertThat(cat.name, is("Samantha")); assertThat(cat.age, is(2)); } @Test public void shouldBeAbleToDeserializeACatWhenAliasConfiguredByAnnotations() { InputStream stream = new ByteArrayInputStream("{\"catAnnotated\":{\"nameAnnotated\": \"Zulu\", \"ageAnnotated\": 1}}".getBytes()); when(provider.parameterNamesFor(annotated.getMethod())).thenReturn(new String[] {"cat"}); Object[] deserialized = deserializer.deserialize(stream, annotated); assertThat(deserialized.length, is(1)); assertThat(deserialized[0], is(instanceOf(CatWithAnnotations.class))); CatWithAnnotations cat = (CatWithAnnotations) deserialized[0]; assertThat(cat.name, is("Zulu")); assertThat(cat.age, is(1)); } }