/*******************************************************************************
* Copyright (c) 2012-2016 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.everrest.core.tools;
import org.everrest.core.FieldInjector;
import org.everrest.core.Parameter;
import org.everrest.core.impl.ConstructorParameter;
import org.everrest.core.impl.FieldInjectorImpl;
import org.everrest.core.impl.method.ParameterResolverFactory;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import static org.everrest.core.util.ParameterizedTypeImpl.newParameterizedType;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
/**
* @author andrew00x
*/
public class DependencySupplierImplTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void providesInstanceByParameter() throws Exception {
DependencySupplierImpl dependencySupplier = createDependencySupplier("foo", -1);
Object instance = dependencySupplier.getInstance(createParameter(String.class, null, null));
assertEquals("foo", instance);
}
@Test
public void providesInstanceProviderByParameter() throws Exception {
DependencySupplierImpl dependencySupplier = createDependencySupplier("foo", -1);
ParameterizedType stringProviderParameterizedType = newParameterizedType(Provider.class, String.class);
Object instance = dependencySupplier.getInstance(createParameter(Provider.class, stringProviderParameterizedType, null));
assertTrue(
String.format("Instance of javax.inject.Provider expected but %s found", instance == null ? "null" : instance.getClass()),
instance instanceof Provider);
assertEquals("foo", ((Provider)instance).get());
}
@Test
public void providesInstanceByType() throws Exception {
DependencySupplierImpl dependencySupplier = createDependencySupplier("foo", -1);
Object instance = dependencySupplier.getInstance(String.class);
assertEquals("foo", instance);
}
public static class SomeType {
@Inject
private String annotated;
@MyInject
private String annotatedWithCustomAnnotation;
@Inject
@Named("SomeName")
private String annotatedAndNamed;
private String notInjectable;
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public static @interface MyInject {
}
@Test
public void providesInstanceForInjectAnnotatedField() throws Exception {
DependencySupplierImpl dependencySupplier = createDependencySupplier("foo", -1);
java.lang.reflect.Field field = SomeType.class.getDeclaredField("annotated");
FieldInjector fieldInjector = createFieldInjector(field);
Object instance = dependencySupplier.getInstance(fieldInjector);
assertEquals("foo", instance);
}
@Test
public void looksUpInstanceForInjectAnnotatedNamedField() throws Exception {
DependencySupplierImpl dependencySupplier = spy(createDependencySupplier("foo", -1));
java.lang.reflect.Field field = SomeType.class.getDeclaredField("annotatedAndNamed");
FieldInjector fieldInjector = createFieldInjector(field);
dependencySupplier.getInstance(fieldInjector);
verify(dependencySupplier).getInstance(fieldInjector);
}
@Test
public void providesInstanceForInjectFieldAnnotatedWithCustomAnnotation() throws Exception {
DependencySupplierImpl dependencySupplier = createDependencySupplier(MyInject.class, "foo", -1);
java.lang.reflect.Field field = SomeType.class.getDeclaredField("annotatedWithCustomAnnotation");
FieldInjector fieldInjector = createFieldInjector(field);
Object instance = dependencySupplier.getInstance(fieldInjector);
assertEquals("foo", instance);
}
@Test
public void providesNullInstanceForNotAnnotatedField() throws Exception {
DependencySupplierImpl dependencySupplier = createDependencySupplier("foo", -1);
java.lang.reflect.Field field = SomeType.class.getDeclaredField("notInjectable");
FieldInjector fieldInjector = createFieldInjector(field);
Object instance = dependencySupplier.getInstance(fieldInjector);
assertNull(instance);
}
@Test
public void providesNullInstanceForFieldsAnnotatedWithNotSupportedAnnotation() throws Exception {
DependencySupplierImpl dependencySupplier = createDependencySupplier("foo", -1);
java.lang.reflect.Field field = SomeType.class.getDeclaredField("annotatedWithCustomAnnotation");
FieldInjector fieldInjector = createFieldInjector(field);
Object instance = dependencySupplier.getInstance(fieldInjector);
assertNull(instance);
}
@Test
public void failsCreateDependencySupplierWithNullInjectAnnotation() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Inject annotation class may not be null");
new DependencySupplierImpl(null);
}
private Parameter createParameter(Class<?> clazz, Type genericType, Annotation[] annotations) {
return new ConstructorParameter(null,
annotations == null ? new Annotation[0] : annotations,
clazz,
genericType,
null,
false);
}
private FieldInjector createFieldInjector(java.lang.reflect.Field field) {
return new FieldInjectorImpl(field, new ParameterResolverFactory());
}
private DependencySupplierImpl createDependencySupplier(Object... instances) {
DependencySupplierImpl dependencySupplier = new DependencySupplierImpl();
for (Object instance : instances) {
dependencySupplier.addInstance(instance.getClass(), instance);
}
return dependencySupplier;
}
private DependencySupplierImpl createDependencySupplier(Class<? extends Annotation> annotationType,
Object... instances) {
DependencySupplierImpl dependencySupplier = new DependencySupplierImpl(annotationType);
for (Object instance : instances) {
dependencySupplier.addInstance(instance.getClass(), instance);
}
return dependencySupplier;
}
}