static methods?

71 views
Skip to first unread message

Tomek Kaczanowski

unread,
Jun 12, 2012, 7:46:45 AM6/12/12
to catch-exception-discuss
Hi,

is it possible to use catch-exception with static method, like:
CatchException.catchException(SomeClass).someStaticMethod(someParams);

--
Regards,
Tomek Kaczanowski

Rod Woo

unread,
Jun 12, 2012, 8:34:39 AM6/12/12
to catch-excep...@googlegroups.com
Hi Tomek,

No, unfortunately, exceptions thrown by static methods cannot be caught
at the moment.

Sometimes I miss that feature, too. But this happens not often because
we rarely use static methods in our code. Even for utility methods like
StringUtils or CollectionUtils we inject beans into our services. For
legacy code we wrap the calls to static methods in non-static methods.
This is an easy way to mock static methods and to catch exceptions as well.

The feature is mainly missing because I have no idea how to implement
it. I probably have to dive into the deepness of PowerMock code to find
a solution.

Do you miss that feature? Let me know. Then I will open an issue as a
first step.

Regards
Rod

Tomek Kaczanowski

unread,
Jun 14, 2012, 11:29:10 AM6/14/12
to catch-exception-discuss
Hi Rod,

it is not that I'm missing this feature very much, however I found a
place where it would be handy. I have a SSHUtils class (static, yes)
which does all sort of SSH things and throws plenty of exceptions. But
as you say, I could also use DI, so it is not a big deal.

--
Regards,
Tomek Kaczanowski

Mridul Khanal

unread,
Feb 12, 2014, 2:59:04 AM2/12/14
to catch-excep...@googlegroups.com
Hey Rod,

While going through the features,I tried to find if this feature by now and stumbled upon this request.

I did not miss this feature till sometime back. 

But now, I am using a lot of heavy operation 'factory methods' for parsing and initializing sort of operations.
It would be very handy.
Another reason where it would help since we can not test for constructor throwing exception, we can wrap that locally

I agree to Tomek that we do not use static a lot and use injections. But that is not true for a lot of initialization of factory based heavy value objects or similar.

- Mridul

rw...@gmx.de

unread,
Feb 13, 2014, 10:18:05 AM2/13/14
to catch-excep...@googlegroups.com
Hi Mridul,

please have a look at the following solution which is based on Powermock. 
The most code is for testing the solution. The actual solution is only a single method. But some Powermock-specific setup must be done as well. This is explained on the Powermock website. 

Give it a go and tell me your opinion.

Rod

public class MyClass {

    public static String myStaticMethod() {
        throw new IllegalStateException("Sorry, bad time for calling!");
    }

    public static String myOtherStaticMethod(int a, String b, int[] c) {
        if (a == 123) {
            throw new IllegalArgumentException("Boring, try other arguments!");
        } else {
            return "Interesting numbers, mate!";
        }
    }
}

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.
     */
    private <T> T catchStaticException(T methodCall)
            throws NoSuchFieldException, IllegalAccessException {

        // 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;
        }
    }

}

Reply all
Reply to author
Forward
0 new messages