/*
* Copyright 2014-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.projection;
import static org.assertj.core.api.Assertions.*;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Proxy;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import org.springframework.aop.Advisor;
import org.springframework.aop.TargetClassAware;
import org.springframework.aop.framework.Advised;
import org.springframework.test.util.ReflectionTestUtils;
/**
* Unit tests for {@link ProxyProjectionFactory}.
*
* @author Oliver Gierke
*/
public class ProxyProjectionFactoryUnitTests {
ProjectionFactory factory = new ProxyProjectionFactory();
@Test(expected = IllegalArgumentException.class) // DATACMNS-630
public void rejectsNullProjectionType() {
factory.createProjection(null);
}
@Test(expected = IllegalArgumentException.class) // DATACMNS-630
public void rejectsNullProjectionTypeWithSource() {
factory.createProjection(null, new Object());
}
@Test(expected = IllegalArgumentException.class) // DATACMNS-630
public void rejectsNullProjectionTypeForInputProperties() {
factory.getInputProperties(null);
}
@Test // DATACMNS-630
public void returnsNullForNullSource() {
assertThat(factory.createProjection(CustomerExcerpt.class, null)).isNull();
}
@Test // DATAREST-221, DATACMNS-630
public void createsProjectingProxy() {
Customer customer = new Customer();
customer.firstname = "Dave";
customer.lastname = "Matthews";
customer.address = new Address();
customer.address.city = "New York";
customer.address.zipCode = "ZIP";
CustomerExcerpt excerpt = factory.createProjection(CustomerExcerpt.class, customer);
assertThat(excerpt.getFirstname()).isEqualTo("Dave");
assertThat(excerpt.getAddress().getZipCode()).isEqualTo("ZIP");
}
@Test // DATAREST-221, DATACMNS-630
@SuppressWarnings("rawtypes")
public void proxyExposesTargetClassAware() {
CustomerExcerpt proxy = factory.createProjection(CustomerExcerpt.class);
assertThat(proxy).isInstanceOf(TargetClassAware.class);
assertThat(((TargetClassAware) proxy).getTargetClass()).isEqualTo(HashMap.class);
}
@Test(expected = IllegalArgumentException.class) // DATAREST-221, DATACMNS-630
public void rejectsNonInterfacesAsProjectionTarget() {
factory.createProjection(Object.class, new Object());
}
@Test // DATACMNS-630
public void createsMapBasedProxyFromSource() {
HashMap<String, Object> addressSource = new HashMap<>();
addressSource.put("zipCode", "ZIP");
addressSource.put("city", "NewYork");
Map<String, Object> source = new HashMap<>();
source.put("firstname", "Dave");
source.put("lastname", "Matthews");
source.put("address", addressSource);
CustomerExcerpt projection = factory.createProjection(CustomerExcerpt.class, source);
assertThat(projection.getFirstname()).isEqualTo("Dave");
AddressExcerpt address = projection.getAddress();
assertThat(address).isNotNull();
assertThat(address.getZipCode()).isEqualTo("ZIP");
}
@Test // DATACMNS-630
public void createsEmptyMapBasedProxy() {
CustomerProxy proxy = factory.createProjection(CustomerProxy.class);
assertThat(proxy).isNotNull();
proxy.setFirstname("Dave");
assertThat(proxy.getFirstname()).isEqualTo("Dave");
}
@Test // DATACMNS-630
public void returnsAllPropertiesAsInputProperties() {
ProjectionInformation projectionInformation = factory.getProjectionInformation(CustomerExcerpt.class);
List<PropertyDescriptor> result = projectionInformation.getInputProperties();
assertThat(result).hasSize(6);
}
@Test // DATACMNS-655
public void invokesDefaultMethodOnProxy() {
CustomerExcerpt excerpt = factory.createProjection(CustomerExcerpt.class);
Advised advised = (Advised) ReflectionTestUtils.getField(Proxy.getInvocationHandler(excerpt), "advised");
Advisor[] advisors = advised.getAdvisors();
assertThat(advisors.length).isGreaterThan(0);
assertThat(advisors[0].getAdvice()).isInstanceOf(DefaultMethodInvokingMethodInterceptor.class);
}
@Test // DATACMNS-648
public void exposesProxyTarget() {
CustomerExcerpt excerpt = factory.createProjection(CustomerExcerpt.class);
assertThat(excerpt).isInstanceOf(TargetAware.class);
assertThat(((TargetAware) excerpt).getTarget()).isInstanceOf(Map.class);
}
@Test // DATACMNS-722
public void doesNotProjectPrimitiveArray() {
Customer customer = new Customer();
customer.picture = "binarydata".getBytes();
CustomerExcerpt excerpt = factory.createProjection(CustomerExcerpt.class, customer);
assertThat(excerpt.getPicture()).isEqualTo(customer.picture);
}
@Test // DATACMNS-722
public void projectsNonPrimitiveArray() {
Address address = new Address();
address.city = "New York";
address.zipCode = "ZIP";
Customer customer = new Customer();
customer.shippingAddresses = new Address[] { address };
CustomerExcerpt excerpt = factory.createProjection(CustomerExcerpt.class, customer);
assertThat(excerpt.getShippingAddresses()).hasSize(1);
}
@Test // DATACMNS-782
public void convertsPrimitiveValues() {
Customer customer = new Customer();
customer.id = 1L;
CustomerExcerpt excerpt = factory.createProjection(CustomerExcerpt.class, customer);
assertThat(excerpt.getId()).isEqualTo(customer.id.toString());
}
@Test // DATACMNS-89
public void exposesProjectionInformationCorrectly() {
ProjectionInformation information = factory.getProjectionInformation(CustomerExcerpt.class);
assertThat(information.getType()).isEqualTo(CustomerExcerpt.class);
assertThat(information.isClosed()).isTrue();
}
@Test // DATACMNS-829
public void projectsMapOfStringToObjectCorrectly() {
Customer customer = new Customer();
customer.data = Collections.singletonMap("key", null);
Map<String, Object> data = factory.createProjection(CustomerExcerpt.class, customer).getData();
assertThat(data).isNotNull();
assertThat(data.containsKey("key")).isTrue();
assertThat(data.get("key")).isNull();
}
static class Customer {
public Long id;
public String firstname, lastname;
public Address address;
public byte[] picture;
public Address[] shippingAddresses;
public Map<String, Object> data;
}
static class Address {
public String zipCode, city;
}
interface CustomerExcerpt {
String getId();
String getFirstname();
AddressExcerpt getAddress();
AddressExcerpt[] getShippingAddresses();
byte[] getPicture();
Map<String, Object> getData();
}
interface AddressExcerpt {
String getZipCode();
}
interface CustomerProxy {
String getFirstname();
void setFirstname(String firstname);
}
}