/*
* Copyright 2016-2017 the original author or authors.
*
* 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 org.springframework.data.web;
import static org.assertj.core.api.Assertions.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.ByteArrayInputStream;
import java.util.List;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;
import com.jayway.jsonpath.spi.mapper.MappingProvider;
/**
* Unit tests for {@link JsonProjectingMethodInterceptorFactory}.
*
* @author Oliver Gierke
* @since 1.13
* @soundtrack Richard Spaven - Assemble (Whole Other*)
*/
public class JsonProjectingMethodInterceptorFactoryUnitTests {
ProjectionFactory projectionFactory;
Customer customer;
@Before
public void setUp() {
String json = "{\"firstname\" : \"Dave\", "//
+ "\"address\" : { \"zipCode\" : \"01097\", \"city\" : \"Dresden\" }," //
+ "\"addresses\" : [ { \"zipCode\" : \"01097\", \"city\" : \"Dresden\" }]" + " }";
SpelAwareProxyProjectionFactory projectionFactory = new SpelAwareProxyProjectionFactory();
MappingProvider mappingProvider = new JacksonMappingProvider(new ObjectMapper());
projectionFactory.registerMethodInvokerFactory(new JsonProjectingMethodInterceptorFactory(mappingProvider));
this.projectionFactory = projectionFactory;
this.customer = projectionFactory.createProjection(Customer.class, new ByteArrayInputStream(json.getBytes()));
}
@Test // DATCMNS-885
public void accessSimpleProperty() {
assertThat(customer.getFirstname()).isEqualTo("Dave");
}
@Test // DATCMNS-885
public void accessPropertyWithExplicitAnnotation() {
assertThat(customer.getBar()).isEqualTo("Dave");
}
@Test // DATCMNS-885
public void accessPropertyWithComplexReturnType() {
assertThat(customer.getAddress()).isEqualTo(new Address("01097", "Dresden"));
}
@Test // DATCMNS-885
public void accessComplexPropertyWithProjection() {
assertThat(customer.getAddressProjection().getCity()).isEqualTo("Dresden");
}
@Test // DATCMNS-885
public void accessPropertyWithNestedJsonPath() {
assertThat(customer.getNestedZipCode()).isEqualTo("01097");
}
@Test // DATCMNS-885
public void accessCollectionProperty() {
assertThat(customer.getAddresses().get(0)).isEqualTo(new Address("01097", "Dresden"));
}
@Test // DATCMNS-885
public void accessPropertyOnNestedProjection() {
assertThat(customer.getAddressProjections().get(0).getZipCode()).isEqualTo("01097");
}
@Test // DATCMNS-885
public void accessPropertyThatUsesJsonPathProjectionInTurn() {
assertThat(customer.getAnotherAddressProjection().getZipCodeButNotCity()).isEqualTo("01097");
}
@Test // DATCMNS-885
public void accessCollectionPropertyThatUsesJsonPathProjectionInTurn() {
List<AnotherAddressProjection> projections = customer.getAnotherAddressProjections();
assertThat(projections).hasSize(1);
assertThat(projections.get(0).getZipCodeButNotCity()).isEqualTo("01097");
}
@Test // DATCMNS-885
public void accessAsCollectionPropertyThatUsesJsonPathProjectionInTurn() {
Set<AnotherAddressProjection> projections = customer.getAnotherAddressProjectionAsCollection();
assertThat(projections).hasSize(1);
assertThat(projections.iterator().next().getZipCodeButNotCity()).isEqualTo("01097");
}
@Test // DATCMNS-885
public void accessNestedPropertyButStayOnRootLevel() {
Name name = customer.getName();
assertThat(name).isNotNull();
assertThat(name.getFirstname()).isEqualTo("Dave");
}
@Test // DATACMNS-885
public void accessNestedFields() {
assertThat(customer.getNestedCity()).isEqualTo("Dresden");
assertThat(customer.getNestedCities()).hasSize(2);
}
interface Customer {
String getFirstname();
@JsonPath("$")
Name getName();
Address getAddress();
List<Address> getAddresses();
@JsonPath("$.addresses")
List<AddressProjection> getAddressProjections();
@JsonPath("$.firstname")
String getBar();
@JsonPath("$.address")
AddressProjection getAddressProjection();
@JsonPath("$.address.zipCode")
String getNestedZipCode();
@JsonPath("$.address")
AnotherAddressProjection getAnotherAddressProjection();
@JsonPath("$.addresses")
List<AnotherAddressProjection> getAnotherAddressProjections();
@JsonPath("$.address")
Set<AnotherAddressProjection> getAnotherAddressProjectionAsCollection();
@JsonPath("$..city")
String getNestedCity();
@JsonPath("$..city")
List<String> getNestedCities();
}
interface AddressProjection {
String getZipCode();
String getCity();
}
interface Name {
@JsonPath("$.firstname")
String getFirstname();
@JsonPath("$.lastname")
String getLastname();
}
interface AnotherAddressProjection {
@JsonPath("$.zipCode")
String getZipCodeButNotCity();
}
@Data
@AllArgsConstructor
@NoArgsConstructor
static class Address {
private String zipCode, city;
}
}