/*
* Copyright (c) 2006-2011 Rogério Liesenfeld
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit;
import java.lang.reflect.*;
/**
* A <em>mock-up</em> for a class or interface, to be used in state-based tests.
* <p/>
* One or more <em>mock methods</em>, each one annotated {@linkplain Mock as such} and corresponding to a "real" method
* or constructor of the mocked class/interface, must be defined in a concrete subclass.
* <p/>
* This class is particularly useful for the creation on <em>in-line mock classes</em>, defined inside individual test
* methods as anonymous inner classes.
* <p/>
* <a href="http://jmockit.googlecode.com/svn/trunk/www/tutorial/StateBasedTesting.html#inline">Tutorial</a>
*
* @param <T> specifies the class or interface(s) to be mocked
*/
public abstract class MockUp<T>
{
private final T mockInstance;
/**
* Applies the mock methods defined in the concrete subclass to the class or interface specified through the type
* parameter.
* <p/>
* When one or more interfaces are specified to be mocked, a mocked proxy class that implements the interfaces is
* created, with the proxy instance made available through a call to {@link #getMockInstance()}.
*
* @see #MockUp(Class)
*/
protected MockUp()
{
ParameterizedType paramType = (ParameterizedType) getClass().getGenericSuperclass();
Type typeToMock = paramType.getActualTypeArguments()[0];
Class<?> classToMock;
if (typeToMock instanceof Class<?>) {
classToMock = (Class<?>) typeToMock;
if (classToMock.isInterface()) {
//noinspection unchecked
mockInstance = (T) Mockit.newEmptyProxy(classToMock);
classToMock = mockInstance.getClass();
}
else {
mockInstance = null;
}
}
else if (typeToMock instanceof TypeVariable) {
//noinspection unchecked
mockInstance = (T) Mockit.newEmptyProxy(typeToMock);
classToMock = mockInstance.getClass();
}
else {
classToMock = (Class<?>) ((ParameterizedType) typeToMock).getRawType();
if (classToMock.isInterface()) {
//noinspection unchecked
mockInstance = (T) Mockit.newEmptyProxy(typeToMock);
classToMock = mockInstance.getClass();
}
else {
mockInstance = null;
}
}
Mockit.setUpMock(classToMock, this);
}
/**
* Applies the mock methods defined in the concrete subclass to the given class.
* <p/>
* In most cases, the constructor with no parameters can be used. This variation should be used only when the real
* class to be mocked is not accessible or known to the test.
*
* @see #MockUp()
*/
protected MockUp(Class<?> classToMock)
{
mockInstance = null;
Mockit.setUpMock(classToMock, this);
}
/**
* Returns the mock instance created for the interface(s) to be mocked specified by the type parameter {@code T}, or
* {@literal null} otherwise (ie, if a class was specified to be mocked).
*/
public final T getMockInstance()
{
return mockInstance;
}
}