/*************************************************************************** * Copyright 2009-2012 by Christian Ihle * * kontakt@usikkert.net * * * * This file is part of KouInject. * * * * KouInject is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of * * the License, or (at your option) any later version. * * * * KouInject is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with KouInject. * * If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ package net.usikkert.kouinject.factory; import static org.junit.Assert.*; import java.lang.reflect.Type; import java.util.List; import net.usikkert.kouinject.generics.TypeLiteral; import net.usikkert.kouinject.beandata.BeanKey; import net.usikkert.kouinject.testbeans.notscanned.factory.InjectFactoryBean; import net.usikkert.kouinject.testbeans.notscanned.factory.StaticFactoryBean; import net.usikkert.kouinject.testbeans.scanned.EverythingBean; import net.usikkert.kouinject.testbeans.scanned.FieldBean; import net.usikkert.kouinject.testbeans.scanned.HelloBean; import net.usikkert.kouinject.testbeans.scanned.coffee.CoffeeBean; import net.usikkert.kouinject.testbeans.scanned.coffee.JavaBean; import net.usikkert.kouinject.testbeans.scanned.factory.ChildFactoryBean; import net.usikkert.kouinject.testbeans.scanned.factory.ChildFactoryCreatedBean; import net.usikkert.kouinject.testbeans.scanned.factory.DifferentTypesFactoryBean; import net.usikkert.kouinject.testbeans.scanned.factory.DifferentTypesFactoryCreatedBean; import net.usikkert.kouinject.testbeans.scanned.factory.FactoryParameterFactoryCreatedBean; import net.usikkert.kouinject.testbeans.scanned.factory.FirstMultipleFactoryCreatedBean; import net.usikkert.kouinject.testbeans.scanned.factory.MultipleFactoryBean; import net.usikkert.kouinject.testbeans.scanned.factory.OneParameterFactoryCreatedBean; import net.usikkert.kouinject.testbeans.scanned.factory.OrangeFactoryBean; import net.usikkert.kouinject.testbeans.scanned.factory.ParameterFactoryBean; import net.usikkert.kouinject.testbeans.scanned.factory.ParentFactoryCreatedBean; import net.usikkert.kouinject.testbeans.scanned.factory.PrivateFactoryBean; import net.usikkert.kouinject.testbeans.scanned.factory.PrivateFactoryCreatedBean; import net.usikkert.kouinject.testbeans.scanned.factory.SecondMultipleFactoryCreatedBean; import net.usikkert.kouinject.testbeans.scanned.factory.SimpleFactoryBean; import net.usikkert.kouinject.testbeans.scanned.factory.SimpleFactoryCreatedBean; import net.usikkert.kouinject.testbeans.scanned.factory.SingletonFactoryBean; import net.usikkert.kouinject.testbeans.scanned.factory.ThirdMultipleFactoryCreatedBean; import net.usikkert.kouinject.testbeans.scanned.factory.ThreeParametersFactoryCreatedBean; import net.usikkert.kouinject.testbeans.scanned.generics.Container; import net.usikkert.kouinject.testbeans.scanned.generics.typevariable.Fanta; import net.usikkert.kouinject.testbeans.scanned.generics.typevariable.FantaBottle; import net.usikkert.kouinject.testbeans.scanned.generics.typevariable.LiquidDualVariableBean; import net.usikkert.kouinject.testbeans.scanned.qualifier.ColorBean; import net.usikkert.kouinject.testbeans.scanned.qualifier.OrangeBean; import net.usikkert.kouinject.testbeans.scanned.qualifier.RedBean; import org.junit.Before; import org.junit.Test; /** * Test of {@link AnnotationBasedFactoryPointHandler}. * * @author Christian Ihle */ public class AnnotationBasedFactoryPointHandlerTest { private AnnotationBasedFactoryPointHandler handler; @Before public void setUp() { handler = new AnnotationBasedFactoryPointHandler(); } @Test public void getFactoryPointsShouldHandleNoFactoryMethods() { final BeanKey factory = new BeanKey(HelloBean.class); final List<FactoryPoint<?>> factoryPoints = handler.getFactoryPoints(factory); assertNotNull(factoryPoints); assertTrue(factoryPoints.isEmpty()); } @Test public void getFactoryPointsShouldFindSingleFactoryMethod() { final BeanKey factory = new BeanKey(SimpleFactoryBean.class); final List<FactoryPoint<?>> factoryPoints = handler.getFactoryPoints(factory); assertNotNull(factoryPoints); assertEquals(1, factoryPoints.size()); final FactoryPoint<?> factoryPoint = factoryPoints.get(0); checkBeanKey(factoryPoint.getReturnType(), SimpleFactoryCreatedBean.class, null); checkBeanKey(factoryPoint.getFactoryKey(), SimpleFactoryBean.class, null); assertFalse(factoryPoint.isSingleton()); assertTrue(factoryPoint.getParameters().isEmpty()); } @Test public void getFactoryPointsShouldFindMultipleFactoryMethods() { final BeanKey factory = new BeanKey(MultipleFactoryBean.class); final List<FactoryPoint<?>> factoryPoints = handler.getFactoryPoints(factory); assertNotNull(factoryPoints); assertEquals(3, factoryPoints.size()); final FactoryPoint<?> factoryPoint1 = getFactoryPointByName(factoryPoints, "createFirstBean"); checkBeanKey(factoryPoint1.getReturnType(), FirstMultipleFactoryCreatedBean.class, null); checkBeanKey(factoryPoint1.getFactoryKey(), MultipleFactoryBean.class, null); assertFalse(factoryPoint1.isSingleton()); assertTrue(factoryPoint1.getParameters().isEmpty()); final FactoryPoint<?> factoryPoint2 = getFactoryPointByName(factoryPoints, "createSecondBean"); checkBeanKey(factoryPoint2.getReturnType(), SecondMultipleFactoryCreatedBean.class, "second"); checkBeanKey(factoryPoint2.getFactoryKey(), MultipleFactoryBean.class, null); assertFalse(factoryPoint2.isSingleton()); assertTrue(factoryPoint2.getParameters().isEmpty()); final FactoryPoint<?> factoryPoint3 = getFactoryPointByName(factoryPoints, "createThirdBean"); checkBeanKey(factoryPoint3.getReturnType(), ThirdMultipleFactoryCreatedBean.class, null); checkBeanKey(factoryPoint3.getFactoryKey(), MultipleFactoryBean.class, null); assertTrue(factoryPoint3.isSingleton()); assertTrue(factoryPoint3.getParameters().isEmpty()); } @Test public void getFactoryPointsShouldFindPrivateFactoryMethods() { final BeanKey factory = new BeanKey(PrivateFactoryBean.class); final List<FactoryPoint<?>> factoryPoints = handler.getFactoryPoints(factory); assertNotNull(factoryPoints); assertEquals(1, factoryPoints.size()); final FactoryPoint<?> factoryPoint = factoryPoints.get(0); checkBeanKey(factoryPoint.getReturnType(), PrivateFactoryCreatedBean.class, null); checkBeanKey(factoryPoint.getFactoryKey(), PrivateFactoryBean.class, null); assertFalse(factoryPoint.isSingleton()); assertTrue(factoryPoint.getParameters().isEmpty()); } @Test public void getFactoryPointsShouldNotReturnMethodsWithoutProducesAnnotation() { final BeanKey factory = new BeanKey(EverythingBean.class); final List<FactoryPoint<?>> factoryPoints = handler.getFactoryPoints(factory); assertNotNull(factoryPoints); assertTrue(factoryPoints.isEmpty()); } @Test public void getFactoryPointsShouldKeepTheQualifierOnTheFactoryKey() { final BeanKey factory = new BeanKey(SimpleFactoryBean.class, "banana"); final List<FactoryPoint<?>> factoryPoints = handler.getFactoryPoints(factory); assertNotNull(factoryPoints); assertEquals(1, factoryPoints.size()); final FactoryPoint<?> factoryPoint = factoryPoints.get(0); checkBeanKey(factoryPoint.getFactoryKey(), SimpleFactoryBean.class, "banana"); } @Test public void getFactoryPointsShouldFindSingletonScopeOnTheMethod() { final BeanKey factory = new BeanKey(SingletonFactoryBean.class); final List<FactoryPoint<?>> factoryPoints = handler.getFactoryPoints(factory); assertNotNull(factoryPoints); assertEquals(1, factoryPoints.size()); final FactoryPoint<?> factoryPoint = factoryPoints.get(0); assertTrue(factoryPoint.isSingleton()); } @Test public void getFactoryPointsShouldFindTheQualifierOfTheMethod() { final BeanKey factory = new BeanKey(OrangeFactoryBean.class); final List<FactoryPoint<?>> factoryPoints = handler.getFactoryPoints(factory); assertNotNull(factoryPoints); assertEquals(1, factoryPoints.size()); final FactoryPoint<?> factoryPoint = factoryPoints.get(0); checkBeanKey(factoryPoint.getReturnType(), OrangeBean.class, "orange"); } @Test public void getFactoryPointsShouldFindTheCorrectParameters() { final BeanKey factory = new BeanKey(ParameterFactoryBean.class); final List<FactoryPoint<?>> factoryPoints = handler.getFactoryPoints(factory); assertNotNull(factoryPoints); assertEquals(3, factoryPoints.size()); // 1 final FactoryPoint<?> factoryPoint1 = getFactoryPointByName(factoryPoints, "createBeanWithOneParameter"); checkBeanKey(factoryPoint1.getReturnType(), OneParameterFactoryCreatedBean.class, null); checkBeanKey(factoryPoint1.getFactoryKey(), ParameterFactoryBean.class, null); assertFalse(factoryPoint1.isSingleton()); assertEquals(1, factoryPoint1.getParameters().size()); checkBeanKey(factoryPoint1.getParameters().get(0), HelloBean.class, null); // 2 final FactoryPoint<?> factoryPoint2 = getFactoryPointByName(factoryPoints, "createBeanWithThreeParameters"); checkBeanKey(factoryPoint2.getReturnType(), ThreeParametersFactoryCreatedBean.class, null); checkBeanKey(factoryPoint2.getFactoryKey(), ParameterFactoryBean.class, null); assertFalse(factoryPoint2.isSingleton()); assertEquals(3, factoryPoint2.getParameters().size()); checkBeanKey(factoryPoint2.getParameters().get(0), ColorBean.class, "Blue"); checkBeanKey(factoryPoint2.getParameters().get(1), CoffeeBean.class, null); checkBeanKey(factoryPoint2.getParameters().get(2), RedBean.class, "red"); // 3 final FactoryPoint<?> factoryPoint3 = getFactoryPointByName(factoryPoints, "createBeanWithFactoryParameter"); checkBeanKey(factoryPoint3.getReturnType(), FactoryParameterFactoryCreatedBean.class, null); checkBeanKey(factoryPoint3.getFactoryKey(), ParameterFactoryBean.class, null); assertFalse(factoryPoint3.isSingleton()); assertEquals(1, factoryPoint3.getParameters().size()); checkBeanKey(factoryPoint3.getParameters().get(0), OneParameterFactoryCreatedBean.class, null); } @Test public void getFactoryPointsShouldFindDifferentParameterTypes() { final BeanKey factory = new BeanKey(DifferentTypesFactoryBean.class); final List<FactoryPoint<?>> factoryPoints = handler.getFactoryPoints(factory); assertNotNull(factoryPoints); assertEquals(1, factoryPoints.size()); final FactoryPoint<?> factoryPoint = factoryPoints.get(0); checkBeanKey(factoryPoint.getReturnType(), DifferentTypesFactoryCreatedBean.class, null); checkBeanKey(factoryPoint.getFactoryKey(), DifferentTypesFactoryBean.class, null); assertFalse(factoryPoint.isSingleton()); assertEquals(4, factoryPoint.getParameters().size()); final BeanKey parameter1 = factoryPoint.getParameters().get(0); checkBeanKey(parameter1, HelloBean.class, null); assertTrue(parameter1.isBeanForCreation()); final BeanKey parameter2 = factoryPoint.getParameters().get(1); checkBeanKey(parameter2, FieldBean.class, null); assertTrue(parameter2.isCollectionProvider()); final BeanKey parameter3 = factoryPoint.getParameters().get(2); checkBeanKey(parameter3, CoffeeBean.class, null); assertTrue(parameter3.isProvider()); final BeanKey parameter4 = factoryPoint.getParameters().get(3); checkBeanKey(parameter4, JavaBean.class, null); assertTrue(parameter4.isCollection()); } @Test public void getFactoryPointsShouldHandleOverriddenMethods() { final BeanKey factory = new BeanKey(ChildFactoryBean.class); final List<FactoryPoint<?>> factoryPoints = handler.getFactoryPoints(factory); assertNotNull(factoryPoints); assertEquals(2, factoryPoints.size()); final FactoryPoint<?> factoryPoint1 = getFactoryPointByName(factoryPoints, "createParentBean"); checkBeanKey(factoryPoint1.getReturnType(), ParentFactoryCreatedBean.class, "parent"); checkBeanKey(factoryPoint1.getFactoryKey(), ChildFactoryBean.class, null); assertFalse(factoryPoint1.isSingleton()); assertTrue(factoryPoint1.getParameters().isEmpty()); final FactoryPoint<?> factoryPoint2 = getFactoryPointByName(factoryPoints, "createChildBean"); checkBeanKey(factoryPoint2.getReturnType(), ChildFactoryCreatedBean.class, "child"); checkBeanKey(factoryPoint2.getFactoryKey(), ChildFactoryBean.class, null); assertFalse(factoryPoint2.isSingleton()); assertTrue(factoryPoint2.getParameters().isEmpty()); } @Test public void getFactoryPointsShouldIgnoreStaticMethods() { final BeanKey factory = new BeanKey(StaticFactoryBean.class); final List<FactoryPoint<?>> factoryPoints = handler.getFactoryPoints(factory); assertNotNull(factoryPoints); assertTrue(factoryPoints.isEmpty()); } @Test(expected = UnsupportedOperationException.class) public void getFactoryPointsShouldFailIfInjectAnnotationPresent() { final BeanKey factory = new BeanKey(InjectFactoryBean.class); handler.getFactoryPoints(factory); } @Test public void getFactoryPointsShouldReturnInvokableFactoryPoints() { final BeanKey factory = new BeanKey(ParameterFactoryBean.class); final List<FactoryPoint<?>> factoryPoints = handler.getFactoryPoints(factory); assertNotNull(factoryPoints); final FactoryPoint<OneParameterFactoryCreatedBean> factoryPoint = (FactoryPoint<OneParameterFactoryCreatedBean>) factoryPoints.get(0); final OneParameterFactoryCreatedBean bean = factoryPoint.create(new ParameterFactoryBean(), new HelloBean()); assertNotNull(bean); } @Test public void getFactoryPointsShouldReplaceTypeVariables() { final List<FactoryPoint<?>> factoryPoints = handler.getFactoryPoints(new BeanKey(FantaBottle.class)); assertEquals(2, factoryPoints.size()); final FactoryPoint<?> factoryPoint1 = getFactoryPointByName(factoryPoints, "createContainer"); final Type factoryPoint1ReturnType = factoryPoint1.getReturnType().getBeanType(); final Type factoryPoint1ExpectedType = new TypeLiteral<Container<Fanta>>() {}.getGenericType(); assertTrue(factoryPoint1ReturnType.equals(factoryPoint1ExpectedType)); final FactoryPoint<?> factoryPoint2 = getFactoryPointByName(factoryPoints, "createDualVariableBean"); final Type factoryPoint2ReturnType = factoryPoint2.getReturnType().getBeanType(); final Type factoryPoint2ExpectedType = new TypeLiteral<LiquidDualVariableBean<Fanta>>() {}.getGenericType(); assertTrue(factoryPoint2ReturnType.equals(factoryPoint2ExpectedType)); } private FactoryPoint<?> getFactoryPointByName(final List<FactoryPoint<?>> factoryPoints, final String name) { for (final FactoryPoint<?> factoryPoint : factoryPoints) { final FactoryPointMethod<?> factoryPointMethod = (FactoryPointMethod<?>) factoryPoint; if (factoryPointMethod.getMethod().getName().equals(name)) { return factoryPoint; } } assertNotNull(null); return null; } private void checkBeanKey(final BeanKey key, final Class<?> aClass, final String qualifier) { assertNotNull(key); assertEquals(aClass, key.getBeanClass()); assertEquals(qualifier, key.getQualifier()); } }