/**
* 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.caughtException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.internal.stubbing.ConsecutiveStubbing;
import org.mockito.internal.stubbing.InvocationContainerImpl;
import org.mockito.internal.stubbing.StubbedInvocationMatcher;
import org.mockito.invocation.Invocation;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.googlecode.catchexception.internal.ExceptionHolder;
/**
* Proof of concept for catching exceptions that are thrown by static methods.
*
* @author rwoo
*
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({ MyClass.class })
@SuppressWarnings("javadoc")
public class PowermockPreparedTest2 {
@Before
public void before() {
PowerMockito.mockStatic(MyClass.class);
}
@Test
public void test_catch_exception_in_static_method_without_parameters()
throws Exception {
catchStaticException(MyClass.myStaticMethod());
assertTrue(caughtException() instanceof IllegalStateException);
}
@Test
public void test_catch_exception_in_static_method_with_parameters()
throws Exception {
catchStaticException(MyClass.myOtherStaticMethod(123, "456", new int[] {
78, 9 }));
assertTrue(caughtException() instanceof IllegalArgumentException);
}
@Test
public void test_catch_exception_in_static_method_with_parameters_no_exception_expected()
throws Exception {
String result = catchStaticException(MyClass.myOtherStaticMethod(42,
"42", new int[] { 42, 42 }));
assertNull(caughtException());
assertEquals("Interesting numbers, mate!", result);
}
/**
* This method could become part of CatchException.
*/
@SuppressWarnings("unchecked")
private <T> T catchStaticException(T methodCall)
throws NoSuchFieldException, IllegalAccessException {
// define that the real method shall be called
ConsecutiveStubbing<String> stubbing = (ConsecutiveStubbing<String>) when(
methodCall).thenCallRealMethod();
// get the method that shall be invoked
Field field = ConsecutiveStubbing.class
.getDeclaredField("invocationContainerImpl");
field.setAccessible(true);
InvocationContainerImpl invocationContainer = (InvocationContainerImpl) field
.get(stubbing);
StubbedInvocationMatcher subbedInvocation = invocationContainer
.getStubbedInvocations().get(0);
Invocation invocation = subbedInvocation.getInvocation();
Method method = invocation.getMethod();
Object[] rawArguments = invocation.getRawArguments();
// invoke the static method
try {
T result = (T) method.invoke(null, rawArguments);
// no exception is thrown
ExceptionHolder.set(null);
return result;
} catch (InvocationTargetException e) {
// exception is thrown
Throwable targetThrowable = e.getTargetException();
if (targetThrowable instanceof Exception) {
ExceptionHolder.set((Exception) targetThrowable);
} else {
// silently ignore the throwable
}
return null;
}
}
}