package com.netflix.governator;
import javax.annotation.PostConstruct;
import javax.inject.Singleton;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import org.mockito.InOrder;
import org.mockito.Mockito;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import junit.framework.Assert;
public class PostConstructTest {
private static class SimplePostConstruct {
@PostConstruct
public void init() {
}
}
private static class InvalidPostConstructs {
@PostConstruct
public String initWithReturnValue() {
return "invalid return type";
}
@PostConstruct
public static void initStatic() {
// can't use static method type
throw new RuntimeException("boom");
}
@PostConstruct
public void initWithParameters(String invalidArg) {
// can't use method parameters
}
}
private static class PostConstructParent1 {
@PostConstruct
public void init() {
System.out.println("parent.init");
}
}
private static class PostConstructChild1 extends PostConstructParent1 {
@PostConstruct
public void init() {
System.out.println("child.init");
}
}
private static class PostConstructParent2 {
@PostConstruct
public void anotherInit() {
System.out.println("parent.anotherInit");
}
}
private static class PostConstructChild2 extends PostConstructParent2 {
@PostConstruct
public void init() {
System.out.println("child.init");
}
}
private static class PostConstructParent3 {
@PostConstruct
public void init() {
}
}
static class PostConstructChild3 extends PostConstructParent3 {
public void init() {
System.out.println("init invoked");
}
}
static class MultiplePostConstructs {
@PostConstruct
public void init1() {
System.out.println("init1");
}
@PostConstruct
public void init2() {
System.out.println("init2");
}
}
@Test
public void testLifecycleInitInheritance1() {
final PostConstructChild1 postConstructChild = Mockito.mock(PostConstructChild1.class);
InOrder inOrder = Mockito.inOrder(postConstructChild);
try (LifecycleInjector injector = TestSupport.inject(postConstructChild)) {
Assert.assertNotNull(injector.getInstance(postConstructChild.getClass()));
// not twice
inOrder.verify(postConstructChild, Mockito.times(1)).init();
}
}
@Test
public void testLifecycleInitInheritance2() {
final PostConstructChild2 postConstructChild = Mockito.mock(PostConstructChild2.class);
InOrder inOrder = Mockito.inOrder(postConstructChild);
try (LifecycleInjector injector = TestSupport.inject(postConstructChild)) {
Assert.assertNotNull(injector.getInstance(postConstructChild.getClass()));
// parent postConstruct before child postConstruct
inOrder.verify(postConstructChild, Mockito.times(1)).anotherInit();
// not twice
inOrder.verify(postConstructChild, Mockito.times(1)).init();
}
}
@Test
public void testLifecycleShutdownInheritance3() {
final PostConstructChild3 postConstructChild = Mockito.spy(new PostConstructChild3());
InOrder inOrder = Mockito.inOrder(postConstructChild);
try (LifecycleInjector injector = TestSupport.inject(postConstructChild)) {
Assert.assertNotNull(injector.getInstance(postConstructChild.getClass()));
Mockito.verify(postConstructChild, Mockito.never()).init();
}
// never, child class overrides method without annotation
inOrder.verify(postConstructChild, Mockito.never()).init();
}
@Test
public void testLifecycleMultipleAnnotations() {
final MultiplePostConstructs multiplePostConstructs = Mockito.spy(new MultiplePostConstructs());
try (LifecycleInjector injector = new TestSupport()
.withFeature(GovernatorFeatures.STRICT_JSR250_VALIDATION, true)
.withSingleton(multiplePostConstructs)
.inject()) {
Assert.assertNotNull(injector.getInstance(multiplePostConstructs.getClass()));
Mockito.verify(multiplePostConstructs, Mockito.never()).init1();
Mockito.verify(multiplePostConstructs, Mockito.never()).init2();
}
// never, multiple annotations should be ignored
Mockito.verify(multiplePostConstructs, Mockito.never()).init1();
Mockito.verify(multiplePostConstructs, Mockito.never()).init2();
}
@Test
public void testLifecycleInitWithInvalidPostConstructs() {
InvalidPostConstructs mockInstance = Mockito.mock(InvalidPostConstructs.class);
try (LifecycleInjector injector = new TestSupport()
.withFeature(GovernatorFeatures.STRICT_JSR250_VALIDATION, true)
.withSingleton(mockInstance)
.inject()) {
Assert.assertNotNull(injector.getInstance(InvalidPostConstructs.class));
Mockito.verify(mockInstance, Mockito.never()).initWithParameters(Mockito.anyString());
Mockito.verify(mockInstance, Mockito.never()).initWithReturnValue();
}
}
@Test
public void testLifecycleInitWithPostConstructException() {
InvalidPostConstructs mockInstance = Mockito.mock(InvalidPostConstructs.class);
try (LifecycleInjector injector = new TestSupport()
.withFeature(GovernatorFeatures.STRICT_JSR250_VALIDATION, true)
.withSingleton(mockInstance)
.inject()) {
Assert.assertNotNull(injector.getInstance(InvalidPostConstructs.class));
Mockito.verify(mockInstance, Mockito.never()).initWithParameters(Mockito.anyString());
Mockito.verify(mockInstance, Mockito.never()).initWithReturnValue();
}
}
@Test
public void testLifecycleInit() {
SimplePostConstruct mockInstance = Mockito.mock(SimplePostConstruct.class);
try (LifecycleInjector injector = TestSupport.inject(mockInstance)) {
Assert.assertNotNull(injector.getInstance(SimplePostConstruct.class));
Mockito.verify(mockInstance, Mockito.times(1)).init();
}
}
@Test
public void testLifecycleInitWithAtProvides() {
final SimplePostConstruct simplePostConstruct = Mockito.mock(SimplePostConstruct.class);
InjectorBuilder builder = InjectorBuilder.fromModule(new AbstractModule() {
@Override
protected void configure() {
}
@Provides
@Singleton
SimplePostConstruct getSimplePostConstruct() {
return simplePostConstruct;
}
});
try (LifecycleInjector injector = builder.createInjector()) {
Mockito.verify(injector.getInstance(SimplePostConstruct.class), Mockito.times(1)).init();
}
}
@Before
public void printTestHeader() {
System.out.println("\n=======================================================");
System.out.println(" Running Test : " + name.getMethodName());
System.out.println("=======================================================\n");
}
@Rule
public TestName name = new TestName();
}