package org.needle4j.postconstruct; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.needle4j.configuration.PostConstructExecuteStrategy.ALWAYS; import static org.needle4j.configuration.PostConstructExecuteStrategy.NEVER; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Set; import javax.annotation.PostConstruct; import org.easymock.EasyMock; import org.junit.Before; import org.junit.Test; import org.needle4j.NeedleContext; import org.needle4j.annotation.ObjectUnderTest; import org.needle4j.reflection.ReflectionUtil; /** * @author Jan Galinski, Holisticon AG (jan.galinski@holisticon.de) */ public class PostConstructProcessorTest { private Runnable runnableMock = EasyMock.createStrictMock(Runnable.class); private Runnable secondRunnableMock = EasyMock.createStrictMock(Runnable.class); private Runnable privateRunnableMock = EasyMock.createStrictMock(Runnable.class); /** * a dummy class without init() */ public class A { } /** * a dummy class with init() */ public class B extends A { @PostConstruct protected void init() { runnableMock.run(); } } /** * used to test postconstruct hierarchy */ public class C extends B { @PostConstruct public void initC() { secondRunnableMock.run(); } } public class PrivatePostConstruct { @SuppressWarnings("unused") @PostConstruct private void init() { privateRunnableMock.run(); } } private static final HashSet<Class<?>> ANNOTATIONS = new HashSet<Class<?>>(); static { ANNOTATIONS.add(PostConstruct.class); } private final PostConstructProcessor postConstructProcessor = new PostConstructProcessor(ANNOTATIONS); // This Processor test does not use the NeeldeRule! @ObjectUnderTest(postConstruct = true) private A isConfiguredForPostConstructionButDoesNotContainMethod = new A(); // This Processor test does not use the NeeldeRule! @ObjectUnderTest(postConstruct = true) private B isConfiguredForPostConstruction = new B(); // This Processor test does not use the NeeldeRule! @ObjectUnderTest private B isNotConfiguredForPostConstruction = new B(); // This Processor test does not use the NeeldeRule! @ObjectUnderTest(postConstruct = true) private C instanceAndParentClassHavePostconstructMethods = new C(); @Before public void setUp() { assertNotNull(postConstructProcessor); } @Test public void testWithoutPostConstructMethod() throws Exception { final NeedleContext context = new NeedleContext(this); final ObjectUnderTest objectUnderTestAnnotation = getObjectUnderTestAnnotation("isConfiguredForPostConstructionButDoesNotContainMethod"); context.addObjectUnderTest(objectUnderTestAnnotation.id(), isConfiguredForPostConstructionButDoesNotContainMethod, objectUnderTestAnnotation); EasyMock.replay(runnableMock); postConstructProcessor.process(context); EasyMock.verify(runnableMock); } @Test public void testWithPostConstructMethod() throws Exception { runnableMock.run(); EasyMock.replay(runnableMock); final NeedleContext context = new NeedleContext(this); final ObjectUnderTest objectUnderTestAnnotation = getObjectUnderTestAnnotation("isConfiguredForPostConstruction"); context.addObjectUnderTest(objectUnderTestAnnotation.id(), isConfiguredForPostConstruction, objectUnderTestAnnotation); postConstructProcessor.process(context); EasyMock.verify(runnableMock); } @Test public void testWithPostConstructMethod_NotConfigured() throws Exception { EasyMock.replay(runnableMock); final NeedleContext context = new NeedleContext(this); final ObjectUnderTest objectUnderTestAnnotation = getObjectUnderTestAnnotation("isNotConfiguredForPostConstruction"); context.addObjectUnderTest(objectUnderTestAnnotation.id(), isNotConfiguredForPostConstruction, objectUnderTestAnnotation); postConstructProcessor.process(context); EasyMock.verify(runnableMock); } @Test public void shouldCallPostConstructOnInstanceAndParent() throws Exception { runnableMock.run(); secondRunnableMock.run(); EasyMock.replay(runnableMock, secondRunnableMock); final NeedleContext context = new NeedleContext(this); final ObjectUnderTest objectUnderTestAnnotation = getObjectUnderTestAnnotation("instanceAndParentClassHavePostconstructMethods"); context.addObjectUnderTest(objectUnderTestAnnotation.id(), instanceAndParentClassHavePostconstructMethods, objectUnderTestAnnotation); postConstructProcessor.process(context); EasyMock.verify(runnableMock, secondRunnableMock); } @Test public void shouldFindTwoPostconstructMethodsForC() throws Exception { final Set<Method> methods = postConstructProcessor.getPostConstructMethods(C.class); assertThat(methods.size(), is(2)); } @Test public void shouldExecuteAlways() { runnableMock.run(); EasyMock.replay(runnableMock); final NeedleContext context = new NeedleContext(this); final ObjectUnderTest objectUnderTestAnnotation = getObjectUnderTestAnnotation("isNotConfiguredForPostConstruction"); context.addObjectUnderTest(objectUnderTestAnnotation.id(), isConfiguredForPostConstruction, objectUnderTestAnnotation); new PostConstructProcessor(ANNOTATIONS, ALWAYS).process(context); EasyMock.verify(runnableMock); } @Test public void shouldExecuteNever() { EasyMock.replay(runnableMock); final NeedleContext context = new NeedleContext(this); final ObjectUnderTest objectUnderTestAnnotation = getObjectUnderTestAnnotation("isConfiguredForPostConstruction"); context.addObjectUnderTest(objectUnderTestAnnotation.id(), isConfiguredForPostConstruction, objectUnderTestAnnotation); new PostConstructProcessor(ANNOTATIONS, NEVER).process(context); EasyMock.verify(runnableMock); } private ObjectUnderTest getObjectUnderTestAnnotation(final String fieldname) { return ReflectionUtil.getField(getClass(), fieldname).getAnnotation(ObjectUnderTest.class); } }