/**
* Copyright (C) 2011 rwoo@gmx.de
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.catchexception;
import static com.googlecode.catchexception.CatchException.catchException;
import static com.googlecode.catchexception.CatchException.caughtException;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
/**
* Tests how PowerMock prepared classes reduce the proxy related limitations of
* {@link CatchException}.
*
* @author rwoo
*
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({ FinalSomethingImpl.class, FinalMethodSomethingImpl.class,
StringBuilder.class, FinalMethodSomethingImpl.class })
@SuppressWarnings("javadoc")
public class PowermockPreparedTest {
// /**
// * Class that encapsulate a mock and its corresponding invocation control.
// */
// private static class MockData<T> {
// private final MockitoMethodInvocationControl methodInvocationControl;
//
// private final T mock;
//
// MockData(MockitoMethodInvocationControl methodInvocationControl, T mock)
// {
// this.methodInvocationControl = methodInvocationControl;
// this.mock = mock;
// }
//
// public MockitoMethodInvocationControl getMethodInvocationControl() {
// return methodInvocationControl;
// }
//
// public T getMock() {
// return mock;
// }
// }
//
// /**
// * Clear state in Mockito that retains memory between tests
// */
// private static class MockitoStateCleaner implements Runnable {
// public void run() {
// clearMockProgress();
// clearConfiguration();
// }
//
// private void clearMockProgress() {
// clearThreadLocalIn(ThreadSafeMockingProgress.class);
// }
//
// private void clearConfiguration() {
// clearThreadLocalIn(GlobalConfiguration.class);
// }
//
// private void clearThreadLocalIn(Class<?> cls) {
// Whitebox.getInternalState(cls, ThreadLocal.class).set(null);
// final Class<?> clazz;
// if (ClassLoaderUtil.hasClass(cls,
// ClassLoader.getSystemClassLoader())) {
// clazz = ClassLoaderUtil.loadClass(cls,
// ClassLoader.getSystemClassLoader());
// } else {
// clazz = ClassLoaderUtil.loadClass(cls, cls.getClassLoader());
// }
// Whitebox.getInternalState(clazz, ThreadLocal.class).set(null);
// }
// }
//
// private static boolean isFinalJavaSystemClass(Class type) {
// return type.getName().startsWith("java.")
// && Modifier.isFinal(type.getModifiers());
// }
//
// private static String toInstanceName(Class clazz) {
// String className = clazz.getSimpleName();
// if (className.length() == 0)
// return clazz.getName();
// else
// return (new StringBuilder())
// .append(className.substring(0, 1).toLowerCase())
// .append(className.substring(1)).toString();
// }
//
// private static <T, E extends Exception> T processException(T obj,
// Class<E> exceptionClazz, boolean assertException) {
//
// if (obj == null) {
// throw new IllegalArgumentException("obj must not be null");
// }
//
// ExceptionProcessingInterceptor<E> interceptor = new
// ExceptionProcessingInterceptor<E>(
// obj, exceptionClazz, assertException);
//
// // PowerMockito.spy(Object object)
// Object object = obj;
// // MockCreator.mock(Whitebox.getType(object), false, true, object, null,
// // (Method[])null);
// Class<T> type = (Class<T>) Whitebox.getType(object);
// boolean isStatic = false;
// boolean isSpy = true;
// Object delegator = object;
// MockSettings mockSettings = null;
// Method methods[] = null;
// // MockCreator.mock(Class type, boolean isStatic, boolean isSpy, Object
// // delegator, MockSettings mockSettings, Method methods[])
// T mock = null;
// String mockName = toInstanceName(type);
// MockRepository.addAfterMethodRunner(new MockitoStateCleaner());
// Class typeToMock;
// if (isFinalJavaSystemClass(type))
// typeToMock = (new ClassReplicaCreator()).createClassReplica(type);
// else
// typeToMock = type;
// MockData<T> mockData = createMethodInvocationControl(mockName,
// typeToMock, methods, isSpy, delegator, mockSettings);
// mock = mockData.getMock();
// if (isFinalJavaSystemClass(type) && !isStatic) {
// mock = Whitebox.newInstance(type);
// DefaultFieldValueGenerator.fillWithDefaultValues(mock);
// }
// if (isStatic)
// MockRepository.putStaticMethodInvocationControl(type,
// mockData.getMethodInvocationControl());
// else
// MockRepository.putInstanceMethodInvocationControl(mock,
// mockData.getMethodInvocationControl());
// if (isSpy)
// (new LenientCopyTool()).copyToMock(delegator, mock);
//
// return mock;
// }
//
// private static <T> MockData<T> createMethodInvocationControl(
// final String mockName, Class<T> type, Method[] methods,
// boolean isSpy, Object delegator, MockSettings mockSettings) {
// final MockSettingsImpl settings;
// if (mockSettings == null) {
// settings = (MockSettingsImpl) Mockito.withSettings();
// } else {
// settings = (MockSettingsImpl) mockSettings;
// }
//
// if (isSpy) {
// settings.defaultAnswer(Mockito.CALLS_REAL_METHODS);
// }
//
// settings.initiateMockName(type);
// MockHandler<T> mockHandler = new MockHandler<T>(settings);
// MethodInterceptorFilter filter = new MethodInterceptorFilter(
// mockHandler, settings);
// final T mock = (T) ClassImposterizer.INSTANCE.imposterise(filter, type);
// final MockitoMethodInvocationControl invocationControl = new
// MockitoMethodInvocationControl(
// filter, isSpy && delegator == null ? new Object() : delegator,
// mock, methods);
//
// return new MockData<T>(invocationControl, mock);
// }
@Test
public void testProxyFactory_KnownLimitation_CannotProxyFinalClass()
throws Exception {
// no limitation :-)
{
FinalSomethingImpl obj = new FinalSomethingImpl();
catchException(obj).doesNotBelongToAnyInterface();
assertNull(caughtException());
}
// no limitation :-)
{
FinalSomethingImpl obj = new FinalSomethingImpl();
catchException(obj).doThrow();
assertTrue(caughtException() instanceof UnsupportedOperationException);
}
// limitation still exists if the proxied class is a Java system class
try {
StringBuilder obj = new StringBuilder();
catchException(obj).charAt(-2);
fail("Exception expected as the class is final");
} catch (ClassCastException e) {
// OK. e.printStackTrace();
// return value of caughtException() is not defined now
}
}
@Test
//FIXME: Powermockito problem
@Ignore
public void testProxyFactory_KnownLimitation_CannotInterceptFinalMethod()
throws Exception {
// limitation still exists if the method is final
try {
FinalMethodSomethingImpl obj = new FinalMethodSomethingImpl();
catchException(obj).doThrow();
fail("UnsupportedOperationException is not expected to be caught");
} catch (UnsupportedOperationException e) {
// OK
// return value of caughtException() is not defined now
}
}
}