All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
mockit.internal.annotations.MockClassSetup Maven / Gradle / Ivy
/*
* Copyright (c) 2006-2013 Rogério Liesenfeld
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit.internal.annotations;
import java.lang.reflect.*;
import java.lang.reflect.Type;
import java.util.*;
import mockit.*;
import mockit.external.asm4.*;
import mockit.internal.*;
import mockit.internal.filtering.*;
import mockit.internal.startup.*;
import mockit.internal.state.*;
import mockit.internal.util.*;
public final class MockClassSetup
{
private Class realClass;
private final Class mockClass;
private ClassReader rcReader;
private final AnnotatedMockMethods mockMethods;
private MockingConfiguration mockingConfiguration;
private final Object mock;
private boolean forStartupMock;
public MockClassSetup(Class mockClass, MockClass metadata)
{
this(metadata.realClass(), null, mockClass, metadata);
}
private MockClassSetup(Class realClass, Object mock, Class mockClass, MockClass metadata)
{
this.realClass = realClass;
validateRealClass();
mockMethods = new AnnotatedMockMethods(realClass, null);
this.mock = mock;
this.mockClass = mockClass;
mockingConfiguration = metadata == null ? null : createMockingConfiguration(metadata);
new AnnotatedMockMethodCollector(mockMethods).collectMockMethods(mockClass);
}
private void validateRealClass()
{
if (realClass.isAnnotationPresent(MockClass.class)) {
throw new IllegalArgumentException("Invalid use of mock " + realClass + " where real class was expected");
}
}
private MockingConfiguration createMockingConfiguration(MockClass metadata)
{
String[] filters = metadata.stubs();
return filters.length == 0 ? null : new MockingConfiguration(filters, !metadata.inverse());
}
public MockClassSetup(Class realClass, Object mock, Class mockClass)
{
this(realClass, mock, mockClass, mockClass.getAnnotation(MockClass.class));
}
public MockClassSetup(Object mock, Class mockClass)
{
this(getRealClass(mockClass), mock, mockClass);
}
public static Class getRealClass(Class specifiedMockClass)
{
MockClass mockClassAnnotation = specifiedMockClass.getAnnotation(MockClass.class);
if (mockClassAnnotation == null) {
throw new IllegalArgumentException("Missing @MockClass for " + specifiedMockClass);
}
@SuppressWarnings("unchecked")
Class realClass = (Class) mockClassAnnotation.realClass();
if (realClass == null) {
// This happens only with the IBM JDK.
throw new TypeNotPresentException("specified in mock " + specifiedMockClass, null);
}
return realClass;
}
public MockClassSetup(Class mockClass)
{
this(getRealClass(mockClass), null, mockClass);
}
public MockClassSetup(Object mockUp)
{
Class mockUpClass = mockUp.getClass();
Type typeToMock = getTypeToMock(mockUpClass);
ParameterizedType mockedType;
if (typeToMock instanceof Class) {
mockedType = null;
realClass = (Class) typeToMock;
}
else if (typeToMock instanceof ParameterizedType){
mockedType = (ParameterizedType) typeToMock;
realClass = (Class) mockedType.getRawType();
}
else {
throw new IllegalArgumentException(
"Invalid target type specified in mock-up " + mockUpClass + ": " + typeToMock);
}
validateRealClass();
mockMethods = new AnnotatedMockMethods(realClass, mockedType);
mock = mockUp;
mockClass = mockUpClass;
new AnnotatedMockMethodCollector(mockMethods).collectMockMethods(mockClass);
}
public static Type getTypeToMock(Class mockUpClass)
{
Class currentClass = mockUpClass;
do {
Type superclass = currentClass.getGenericSuperclass();
if (superclass instanceof ParameterizedType) {
return ((ParameterizedType) superclass).getActualTypeArguments()[0];
}
else if (superclass == MockUp.class) {
throw new IllegalArgumentException("No type to be mocked");
}
currentClass = (Class) superclass;
}
while (true);
}
public MockClassSetup(Class realClass, ParameterizedType mockedType, Object mockUp, byte[] realClassCode)
{
this.realClass = realClass;
validateRealClass();
mockMethods = new AnnotatedMockMethods(realClass, mockedType);
mock = mockUp;
mockClass = mockUp.getClass();
rcReader = realClassCode == null ? null : new ClassReader(realClassCode);
new AnnotatedMockMethodCollector(mockMethods).collectMockMethods(mockClass);
}
public void setUpStartupMock()
{
if (realClass != null) {
forStartupMock = true;
redefineMethods();
}
}
public Set> redefineMethods()
{
Set> redefinedClasses = redefineMethodsInClassHierarchy();
validateThatAllMockMethodsWereApplied();
return redefinedClasses;
}
private Set> redefineMethodsInClassHierarchy()
{
Set> redefinedClasses = new HashSet>();
while (realClass != null && (mockingConfiguration != null || mockMethods.hasUnusedMocks())) {
byte[] modifiedClassFile = modifyRealClass();
if (modifiedClassFile != null) {
applyClassModifications(modifiedClassFile);
redefinedClasses.add(realClass);
}
Class superClass = realClass.getSuperclass();
realClass = superClass == Object.class || superClass == Proxy.class ? null : superClass;
rcReader = null;
mockingConfiguration = null;
}
return redefinedClasses;
}
private byte[] modifyRealClass()
{
if (rcReader == null) {
rcReader = createClassReaderForRealClass();
}
MockupsModifier modifier =
new MockupsModifier(rcReader, realClass, mock, mockMethods, mockingConfiguration, forStartupMock);
rcReader.accept(modifier, 0);
return modifier.wasModified() ? modifier.toByteArray() : null;
}
private ClassReader createClassReaderForRealClass()
{
if (realClass.isInterface() || realClass.isArray()) {
throw new IllegalArgumentException("Not a modifiable class: " + realClass.getName());
}
return ClassFile.createReaderFromLastRedefinitionIfAny(realClass);
}
private void applyClassModifications(byte[] modifiedClassFile)
{
Startup.redefineMethods(realClass, modifiedClassFile);
mockMethods.registerMockStates();
if (forStartupMock) {
CachedClassfiles.addClassfile(realClass, modifiedClassFile);
}
else {
TestRun.mockFixture().addRedefinedClass(mockMethods.getMockClassInternalName(), realClass, modifiedClassFile);
}
}
private void validateThatAllMockMethodsWereApplied()
{
List remainingMocks = mockMethods.getUnusedMockSignatures();
if (!remainingMocks.isEmpty()) {
String classDesc = mockMethods.getMockClassInternalName();
String mockSignatures = new MethodFormatter(classDesc).friendlyMethodSignatures(remainingMocks);
throw new IllegalArgumentException(
"Matching real methods not found for the following mocks:\n" + mockSignatures);
}
}
}