/* * Copyright (c) 2007 Mockito contributors * This program is made available under the terms of the MIT License. */ package org.mockito.internal.util.reflection; import org.junit.Test; import org.mockito.InjectMocks; import org.mockito.Mockito; import org.mockito.exceptions.base.MockitoException; import org.mockito.internal.util.reflection.FieldInitializer.ConstructorArgumentResolver; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import static org.junit.Assert.*; import static org.mockito.BDDMockito.given; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; public class FieldInitializerTest { private StaticClass alreadyInstantiated = new StaticClass(); private StaticClass noConstructor; private StaticClassWithDefaultConstructor defaultConstructor; private StaticClassWithPrivateDefaultConstructor privateDefaultConstructor; private StaticClassWithoutDefaultConstructor noDefaultConstructor; private StaticClassThrowingExceptionDefaultConstructor throwingExDefaultConstructor; private AbstractStaticClass abstractType; private Interface interfaceType; private InnerClassType innerClassType; private AbstractStaticClass instantiatedAbstractType = new ConcreteStaticClass(); private Interface instantiatedInterfaceType = new ConcreteStaticClass(); private InnerClassType instantiatedInnerClassType = new InnerClassType(); @Test public void should_keep_same_instance_if_field_initialized() throws Exception { final StaticClass backupInstance = alreadyInstantiated; FieldInitializer fieldInitializer = new FieldInitializer(this, field("alreadyInstantiated")); FieldInitializationReport report = fieldInitializer.initialize(); assertSame(backupInstance, report.fieldInstance()); assertFalse(report.fieldWasInitialized()); assertFalse(report.fieldWasInitializedUsingContructorArgs()); } @Test public void should_instantiate_field_when_type_has_no_constructor() throws Exception { FieldInitializer fieldInitializer = new FieldInitializer(this, field("noConstructor")); FieldInitializationReport report = fieldInitializer.initialize(); assertNotNull(report.fieldInstance()); assertTrue(report.fieldWasInitialized()); assertFalse(report.fieldWasInitializedUsingContructorArgs()); } @Test public void should_instantiate_field_with_default_constructor() throws Exception { FieldInitializer fieldInitializer = new FieldInitializer(this, field("defaultConstructor")); FieldInitializationReport report = fieldInitializer.initialize(); assertNotNull(report.fieldInstance()); assertTrue(report.fieldWasInitialized()); assertFalse(report.fieldWasInitializedUsingContructorArgs()); } @Test public void should_instantiate_field_with_private_default_constructor() throws Exception { FieldInitializer fieldInitializer = new FieldInitializer(this, field("privateDefaultConstructor")); FieldInitializationReport report = fieldInitializer.initialize(); assertNotNull(report.fieldInstance()); assertTrue(report.fieldWasInitialized()); assertFalse(report.fieldWasInitializedUsingContructorArgs()); } @Test(expected = MockitoException.class) public void should_fail_to_instantiate_field_if_no_default_constructor() throws Exception { FieldInitializer fieldInitializer = new FieldInitializer(this, field("noDefaultConstructor")); fieldInitializer.initialize(); } @Test public void should_fail_to_instantiate_field_if_default_constructor_throws_exception() throws Exception { FieldInitializer fieldInitializer = new FieldInitializer(this, field("throwingExDefaultConstructor")); try { fieldInitializer.initialize(); fail(); } catch (MockitoException e) { InvocationTargetException ite = (InvocationTargetException) e.getCause(); assertTrue(ite.getTargetException() instanceof NullPointerException); assertEquals("business logic failed", ite.getTargetException().getMessage()); } } @Test(expected = MockitoException.class) public void should_fail_for_abstract_field() throws Exception { new FieldInitializer(this, field("abstractType")); } @Test public void should_not_fail_if_abstract_field_is_instantiated() throws Exception { new FieldInitializer(this, field("instantiatedAbstractType")); } @Test(expected = MockitoException.class) public void should_fail_for_interface_field() throws Exception { new FieldInitializer(this, field("interfaceType")); } @Test public void should_not_fail_if_interface_field_is_instantiated() throws Exception { new FieldInitializer(this, field("instantiatedInterfaceType")); } @Test(expected = MockitoException.class) public void should_fail_for_local_type_field() throws Exception { // when class LocalType { } class TheTestWithLocalType { @InjectMocks LocalType field; } TheTestWithLocalType testWithLocalType = new TheTestWithLocalType(); // when new FieldInitializer(testWithLocalType, testWithLocalType.getClass().getDeclaredField("field")); } @Test public void should_not_fail_if_local_type_field_is_instantiated() throws Exception { // when class LocalType { } class TheTestWithLocalType { @InjectMocks LocalType field = new LocalType(); } TheTestWithLocalType testWithLocalType = new TheTestWithLocalType(); // when new FieldInitializer(testWithLocalType, testWithLocalType.getClass().getDeclaredField("field")); } @Test(expected = MockitoException.class) public void should_fail_for_inner_class_field() throws Exception { new FieldInitializer(this, field("innerClassType")); } @Test public void should_not_fail_if_inner_class_field_is_instantiated() throws Exception { new FieldInitializer(this, field("instantiatedInnerClassType")); } @Test public void can_instantiate_class_with_parameterized_constructor() throws Exception { ConstructorArgumentResolver resolver = given(mock(ConstructorArgumentResolver.class).resolveTypeInstances(any(Class.class))) .willReturn(new Object[]{null}).getMock(); new FieldInitializer(this, field("noDefaultConstructor"), resolver).initialize(); assertNotNull(noDefaultConstructor); } private Field field(String fieldName) throws NoSuchFieldException { return this.getClass().getDeclaredField(fieldName); } static class StaticClass { } static class StaticClassWithDefaultConstructor { StaticClassWithDefaultConstructor() { } } static class StaticClassWithPrivateDefaultConstructor { private StaticClassWithPrivateDefaultConstructor() { } } static class StaticClassWithoutDefaultConstructor { private StaticClassWithoutDefaultConstructor(String param) { } } static class StaticClassThrowingExceptionDefaultConstructor { StaticClassThrowingExceptionDefaultConstructor() throws Exception { throw new NullPointerException("business logic failed"); } } static abstract class AbstractStaticClass { public AbstractStaticClass() {} } interface Interface { } static class ConcreteStaticClass extends AbstractStaticClass implements Interface { } class InnerClassType { InnerClassType() { } } }