/*
* Copyright (c) 2006 Rogério Liesenfeld
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit;
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
import org.junit.*;
import org.junit.rules.*;
import static org.junit.Assert.*;
import mockit.internal.util.*;
import static mockit.Deencapsulation.*;
import static org.hamcrest.CoreMatchers.*;
@SuppressWarnings("unused")
public final class DeencapsulationTest
{
@Rule public final ExpectedException thrown = ExpectedException.none();
static final class Subclass extends BaseClass
{
final int INITIAL_VALUE = new Random().nextInt();
final int initialValue = -1;
private static final Integer constantField = 123;
private static StringBuilder buffer;
private static char static1;
private static char static2;
static StringBuilder getBuffer() { return buffer; }
static void setBuffer(StringBuilder buffer) { Subclass.buffer = buffer; }
private String stringField;
private int intField;
private int intField2;
private List<String> listField;
Subclass() { intField = -1; }
Subclass(int a, String b) { intField = a; stringField = b; }
Subclass(String... args) { listField = Arrays.asList(args); }
Subclass(List<String> list) { listField = list; }
private static Boolean anStaticMethod() { return true; }
private static void staticMethod(short s, String str, Boolean b) {}
private static String staticMethod(short s, StringBuilder str, boolean b) { return String.valueOf(str); }
private long aMethod() { return 567L; }
private void instanceMethod(short s, String str, Boolean b) {}
private String instanceMethod(short s, StringBuilder str, boolean b) { return String.valueOf(str); }
int getIntField() { return intField; }
void setIntField(int intField) { this.intField = intField; }
int getIntField2() { return intField2; }
void setIntField2(int intField2) { this.intField2 = intField2; }
String getStringField() { return stringField; }
void setStringField(String stringField) { this.stringField = stringField; }
List<String> getListField() { return listField; }
void setListField(List<String> listField) { this.listField = listField; }
private final class InnerClass
{
private InnerClass() {}
private InnerClass(boolean b, Long l, String s) {}
private InnerClass(List<String> list) {}
}
}
static final Class<?> innerClass = ClassLoad.loadClass(Subclass.class.getName() + "$InnerClass");
final Subclass anInstance = new Subclass();
@Test
public void getInstanceFieldByName()
{
anInstance.setIntField(3);
anInstance.setStringField("test");
anInstance.setListField(Collections.<String>emptyList());
Integer intValue = getField(anInstance, "intField");
String stringValue = getField(anInstance, "stringField");
List<String> listValue = getField(anInstance, "listField");
assertEquals(anInstance.getIntField(), intValue.intValue());
assertEquals(anInstance.getStringField(), stringValue);
assertSame(anInstance.getListField(), listValue);
}
@Test
public void attemptToGetInstanceFieldByNameWithWrongName()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("No instance field of name \"noField\" found");
getField(anInstance, "noField");
}
@Test
public void getInheritedInstanceFieldByName()
{
anInstance.baseInt = 3;
anInstance.baseString = "test";
anInstance.baseSet = Collections.emptySet();
Integer intValue = getField(anInstance, "baseInt");
String stringValue = getField(anInstance, "baseString");
Set<Boolean> listValue = getField(anInstance, "baseSet");
assertEquals(anInstance.baseInt, intValue.intValue());
assertEquals(anInstance.baseString, stringValue);
assertSame(anInstance.baseSet, listValue);
}
@Test @SuppressWarnings("unchecked")
public void getInstanceFieldByType()
{
anInstance.setStringField("by type");
anInstance.setListField(new ArrayList<String>());
String stringValue = getField(anInstance, String.class);
List<String> listValue = getField(anInstance, List.class);
List<String> listValue2 = getField(anInstance, ArrayList.class);
assertEquals(anInstance.getStringField(), stringValue);
assertSame(anInstance.getListField(), listValue);
assertSame(listValue, listValue2);
}
@Test
public void attemptToGetInstanceFieldByTypeWithWrongType()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Instance field of type byte or Byte not found");
getField(anInstance, Byte.class);
}
@Test
public void attemptToGetInstanceFieldByTypeForClassWithMultipleFieldsOfThatType()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("More than one instance field");
thrown.expectMessage("of type int ");
thrown.expectMessage("INITIAL_VALUE, initialValue");
getField(anInstance, int.class);
}
@Test @SuppressWarnings("unchecked")
public void getInheritedInstanceFieldByType()
{
Set<Boolean> fieldValueOnInstance = new HashSet<Boolean>();
anInstance.baseSet = fieldValueOnInstance;
Set<Boolean> setValue = getField(anInstance, fieldValueOnInstance.getClass());
Set<Boolean> setValue2 = getField(anInstance, HashSet.class);
assertSame(fieldValueOnInstance, setValue);
assertSame(setValue, setValue2);
}
@Test
public void getInstanceFieldOnBaseClassByType()
{
anInstance.setLongField(15);
long longValue = getField(anInstance, long.class);
assertEquals(15, longValue);
}
@Test
public void getStaticFieldByName()
{
Subclass.setBuffer(new StringBuilder());
StringBuilder b = getField(Subclass.class, "buffer");
assertSame(Subclass.getBuffer(), b);
}
@Test
public void attemptToGetStaticFieldByNameFromWrongClass()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("No static field of name \"buffer\" found in class mockit.BaseClass");
getField(BaseClass.class, "buffer");
}
@Test
public void getStaticFieldByType()
{
Subclass.setBuffer(new StringBuilder());
StringBuilder b = getField(Subclass.class, StringBuilder.class);
assertSame(Subclass.getBuffer(), b);
}
@Test
public void setInstanceFieldByName()
{
anInstance.setIntField2(1);
setField(anInstance, "intField2", 901);
assertEquals(901, anInstance.getIntField2());
}
@Test
public void attemptToSetInstanceFieldByNameWithWrongName()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("No instance field of name \"noField\" found");
setField(anInstance, "noField", 901);
}
@Test
public void setInstanceFieldByType()
{
anInstance.setStringField("");
setField(anInstance, "Test");
assertEquals("Test", anInstance.getStringField());
}
@Test
public void attemptToSetInstanceFieldByTypeWithWrongType()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Instance field of type byte or Byte not found");
setField(anInstance, (byte) 123);
}
@Test
public void attemptToSetInstanceFieldByTypeForClassWithMultipleFieldsOfThatType()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("More than one instance field ");
setField(anInstance, 901);
}
@Test
public void setStaticFieldByName()
{
Subclass.setBuffer(null);
setField(Subclass.class, "buffer", new StringBuilder());
assertNotNull(Subclass.getBuffer());
}
@Test
public void attemptToSetStaticFieldByNameWithWrongName()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("No static field of name \"noField\" found ");
setField(Subclass.class, "noField", null);
}
@Test
public void setStaticFieldByType()
{
Subclass.setBuffer(null);
setField(Subclass.class, new StringBuilder());
assertNotNull(Subclass.getBuffer());
}
@Test
public void attemptToSetFieldByTypeWithoutAValue()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Missing field value");
setField(Subclass.class, null);
}
@Test
public void attemptToSetStaticFieldByTypeWithWrongType()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Static field of type StringBuffer not found");
setField(Subclass.class, new StringBuffer());
}
@Test
public void attemptToSetStaticFieldByTypeForClassWithMultipleFieldsOfThatType()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("More than one static field ");
setField(Subclass.class, 'A');
}
@Test
public void setFinalInstanceFields()
{
Subclass obj = new Subclass();
setField(obj, "INITIAL_VALUE", 123);
setField(obj, "initialValue", 123);
assertEquals(123, obj.INITIAL_VALUE);
assertEquals(123, getField(obj, "initialValue"));
assertEquals(-1, obj.initialValue); // in this case, the compile-time constant gets embedded in client code
}
@Test
public void attemptToSetAStaticFinalField()
{
thrown.expectCause(isA(IllegalAccessException.class));
setField(Subclass.class, "constantField", 54);
}
@Test
public void invokeInstanceMethodWithoutParameters()
{
Long result = invoke(anInstance, "aMethod");
assertEquals(567L, result.longValue());
}
@Test
public void invokeInstanceMethodWithSpecifiedParameterTypes()
{
String result =
invoke(
anInstance, "instanceMethod",
new Class<?>[] {short.class, StringBuilder.class, boolean.class},
(short) 7, new StringBuilder("abc"), true);
assertEquals("abc", result);
}
@Test
public void invokeInstanceMethodWithMultipleParameters()
{
assertNull(invoke(anInstance, "instanceMethod", (short) 7, "abc", true));
String result = invoke(anInstance, "instanceMethod", (short) 7, new StringBuilder("abc"), true);
assertEquals("abc", result);
}
@Test
public void invokeInstanceMethodWithNullArgumentsSpecifiedThroughClassLiterals()
{
assertNull(invoke(anInstance, "instanceMethod", (short) 7, String.class, Boolean.class));
String result = invoke(anInstance, "instanceMethod", (short) 7, StringBuilder.class, true);
assertEquals("null", result);
}
@Test
public void attemptToInvokeNonExistentInstanceMethod()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("No compatible method found");
thrown.expectMessage("notAMethod()");
invoke(anInstance, "notAMethod");
}
@Test
public void attemptToInvokeNonExistentStaticMethod()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("No compatible static method found");
thrown.expectMessage("notAMethod()");
invoke(Subclass.class, "notAMethod");
}
@Test
public void attemptToInvokeNonExistentMethodByNameAndParameterTypes()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Specified method not found");
thrown.expectMessage("notAMethod(int)");
invoke(anInstance, "notAMethod", new Class<?>[] {int.class}, 123);
}
@Test
public void attemptToInvokeInstanceMethodWithInvalidNullArgument()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Invalid null ");
thrown.expectMessage(" argument 1");
invoke(anInstance, "instanceMethod", (short) 7, null, true);
}
@Test
public void attemptToInvokeMethodWithNameAndParameterTypesButInvalidNullArgument()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Invalid null ");
Class<?>[] parameterTypes = {short.class, String.class, Boolean.class};
invoke(anInstance, "instanceMethod", parameterTypes, (Object[]) null);
}
@Test
public void attemptToInvokeInstanceMethodWithNullVarargs()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Invalid null value passed as argument");
//noinspection NullArgumentToVariableArgMethod
invoke(anInstance, "instanceMethod", null);
}
@Test
public void invokeInstanceMethodWithSingleParameterOfBaseTypeWhilePassingSubtypeInstance()
{
invoke(anInstance, "setListField", new ArrayList<String>());
}
@Test
public void invokeStaticMethodWithoutParameters()
{
Boolean result = invoke(Subclass.class, "anStaticMethod");
assertTrue(result);
}
@Test
public void invokeStaticMethodByClassNameWithoutParameters()
{
Boolean result = invoke(Subclass.class.getName(), "anStaticMethod");
assertTrue(result);
}
@Test
public void invokeStaticMethodWithSpecifiedParameterTypes()
{
String result =
invoke(
Subclass.class, "staticMethod",
new Class<?>[] {short.class, StringBuilder.class, boolean.class},
(short) 7, new StringBuilder("abc"), true);
assertEquals("abc", result);
}
@Test
public void invokeStaticMethodWithMultipleParameters()
{
assertNull(invoke(Subclass.class, "staticMethod", (short) 7, "abc", true));
String result = invoke(Subclass.class, "staticMethod", (short) 7, new StringBuilder("abc"), true);
assertEquals("abc", result);
}
@Test
public void invokeStaticMethodByClassNameWithMultipleParameters()
{
Object result = invoke(Subclass.class.getName(), "staticMethod", (short) 7, "abc", true);
assertNull(result);
}
@Test
public void attemptToInvokeMethodByClassNameOnUnavailableClass()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("No class with name \"abc.xyz.NoClass\" found");
invoke("abc.xyz.NoClass", "aMethod");
}
@Test
public void invokeStaticMethodWithNullArgumentsSpecifiedThroughClassLiterals()
{
assertNull(invoke(anInstance, "staticMethod", (short) 7, String.class, Boolean.class));
String result = invoke(anInstance, "staticMethod", (short) 7, StringBuilder.class, true);
assertEquals("null", result);
}
@Test
public void attemptToInvokeStaticMethodWithInvalidNullArgument()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Invalid null value ");
thrown.expectMessage(" argument 1");
invoke(anInstance, "staticMethod", (short) 7, null, true);
}
@Test
public void attemptToInvokeMethodWithNonMatchingArrayArguments()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("No compatible method found");
thrown.expectMessage("int[]");
thrown.expectMessage("String[]");
thrown.expectMessage("java.util.List[]");
invoke(anInstance, "aMethod", "test", 1, 2.0, new int[0], new String[0], new List<?>[0], new ArrayList<Long>());
}
@Test
public void attemptToInvokeInstanceMethodAsAnStaticMethod()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Attempted to invoke non-static method without an instance");
invoke(anInstance.getClass(), "instanceMethod", (short) 7, "test", true);
}
@Test
public void attemptToInvokeInstanceMethodAsAnStaticMethodUsingClassName()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Attempted to invoke non-static method without an instance");
invoke(anInstance.getClass().getName(), "instanceMethod", (short) 7, "test", true);
}
@Test
public void newInstanceUsingNoArgsConstructorFromSpecifiedParameterTypes()
{
Class<?>[] parameterTypes = {};
Subclass instance = newInstance(Subclass.class.getName(), (Object[]) parameterTypes);
assertNotNull(instance);
assertEquals(-1, instance.getIntField());
}
@Test
public void newInstanceUsingNoArgsConstructorWithoutSpecifyingParameters()
{
Subclass instance = newInstance(Subclass.class.getName());
assertNotNull(instance);
assertEquals(-1, instance.getIntField());
}
@Test
public void attemptToInvokeConstructorWithNullVarargs()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Invalid null value passed as argument");
//noinspection NullArgumentToVariableArgMethod
newInstance(Subclass.class.getName(), null);
}
@Test
public void newInstanceByNameUsingMultipleArgsConstructorFromSpecifiedParameterTypes()
{
Subclass instance = newInstance(Subclass.class.getName(), new Class<?>[] {int.class, String.class}, 1, "XYZ");
assertNotNull(instance);
assertEquals(1, instance.getIntField());
assertEquals("XYZ", instance.getStringField());
}
@Test
public void newInstanceUsingMultipleArgsConstructorFromSpecifiedParameterTypes()
{
BaseClass instance = newInstance(Subclass.class, new Class<?>[] {int.class, String.class}, 1, "XYZ");
assertNotNull(instance);
}
@Test
public void attemptNewInstanceWithInvalidNullArgument()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Invalid null value");
newInstance(Subclass.class, (Object[]) null);
}
@Test
public void attemptNewInstanceWithParameterTypesButInvalidNullArgument()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Invalid null value");
newInstance(Subclass.class, new Class<?>[] {int.class, String.class}, (Object[]) null);
}
@Test
public void attemptNewInstanceWithNoMatchingConstructor()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Specified constructor not found: Subclass(char)");
newInstance(Subclass.class.getName(), new Class<?>[] {char.class}, 'z');
}
@Test
public void newInstanceByNameUsingMultipleArgsConstructorFromNonNullArgumentValues()
{
Subclass instance = newInstance(Subclass.class.getName(), 590, "");
assertNotNull(instance);
assertEquals(590, instance.getIntField());
assertEquals("", instance.getStringField());
}
@Test
public void attemptNewInstanceForNonExistentConstructorByClassNameAndArgumentValues()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("No compatible constructor found");
thrown.expectMessage("Subclass(Integer)");
newInstance(Subclass.class.getName(), 123);
}
@Test
public void attemptNewInstanceByNameUsingMultipleArgsConstructorWithInvalidNullArgument()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Invalid null value");
thrown.expectMessage(" argument 1");
newInstance(Subclass.class.getName(), 590, null);
}
@Test
public void newInstancePassingSubclassInstanceToConstructorWithSingleArgument()
{
List<String> aList = new ArrayList<String>();
Subclass instance = newInstance(Subclass.class, aList);
assertNotNull(instance);
assertSame(aList, instance.getListField());
}
@Test
public void newInstanceUsingMultipleArgsConstructorFromNonNullArgumentValues()
{
BaseClass instance = newInstance(Subclass.class, 590, "");
assertNotNull(instance);
}
@Test
public void newInnerInstanceUsingNoArgsConstructor()
{
Object innerInstance = newInnerInstance("InnerClass", anInstance);
assertTrue(innerClass.isInstance(innerInstance));
}
class InnerClass { InnerClass(int i) {} }
@Test
public void instantiateInnerClassWithOwnerInstance()
{
InnerClass ic = newInstance(InnerClass.class, this, 123);
assertNotNull(ic);
}
@Test
public void attemptToInstantiateInnerClassWithoutOwnerInstance()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("instantiation of inner class");
newInstance(InnerClass.class, 123);
}
@Test
public void attemptToInstantiateInnerInstanceWithWrongInnerClassName()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("No class with name ");
thrown.expectMessage("$NoClass\" found");
newInnerInstance("NoClass", anInstance);
}
@Test
public void attemptToInvokeConstructorForInnerClassWithNullVarargs()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Invalid null value passed as argument");
//noinspection NullArgumentToVariableArgMethod
newInnerInstance("InnerClass", anInstance, null);
}
@Test
public void newInnerInstanceByNameUsingMultipleArgsConstructor()
{
Object innerInstance = newInnerInstance("InnerClass", anInstance, true, 5L, "");
assertTrue(innerClass.isInstance(innerInstance));
}
@Test
public void attemptToInstantiateInnerInstanceByNameUsingMultipleArgsConstructorWithInvalidNullArguments()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Invalid null value");
newInnerInstance("InnerClass", anInstance, false, null, null);
}
@Test
public void newInnerInstanceUsingMultipleArgsConstructor()
{
Object innerInstance = newInnerInstance(innerClass, anInstance, true, 5L, "");
assertTrue(innerClass.isInstance(innerInstance));
}
@Test
public void newInnerInstancePassingSubclassInstanceToConstructorWithSingleArgument()
{
List<String> aList = new ArrayList<String>();
Object innerInstance = newInnerInstance(innerClass, anInstance, aList);
assertTrue(innerClass.isInstance(innerInstance));
}
@Test
public void attemptToInstantiateNestedClassAsIfItWasInnerClass()
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Subclass is not an inner class");
newInnerInstance(Subclass.class, this);
}
@Test(expected = InstantiationException.class)
public void causeInstantiationExceptionToBeThrown() throws Exception
{
//noinspection ClassNewInstance
Runnable.class.newInstance();
}
@Test
public void newUninitializedInstanceOfConcreteClass()
{
Subclass instance = newUninitializedInstance(Subclass.class);
assertEquals(0, instance.intField);
assertEquals(0, instance.INITIAL_VALUE);
assertEquals(-1, instance.initialValue);
// This field value is a compile-time constant, so we need Reflection to read its current value:
int initialValue = getField(instance, "initialValue");
assertEquals(0, initialValue);
}
public abstract static class AbstractClass implements Runnable { protected abstract int doSomething(); }
@Test
public void newUninitializedInstanceOfAbstractClass()
{
AbstractClass instance = newUninitializedInstance(AbstractClass.class);
assertNotNull(instance);
assertEquals(0, instance.doSomething());
instance.run();
}
@Test
public void newUninitializedInstanceOfAbstractJREClass() throws Exception
{
Writer instance = newUninitializedInstance(Writer.class);
assertNotNull(instance);
assertNull(getField(instance, "lock"));
// Abstract methods.
instance.write(new char[0], 0, 0);
instance.flush();
instance.close();
// Regular methods.
try {
instance.write(123);
fail();
}
catch (NullPointerException ignore) {}
}
@Test
public void newUninitializedInstanceOfInterface() throws Exception
{
Callable<?> callable = newUninitializedInstance(Callable.class);
assertNotNull(callable);
assertNull(callable.call());
}
}