Testing reflection newInstance exception

2019-07-06 05:31发布

问题:

I'm using a very limited set of reflection in this piece of code:

public NetworkClient createNetworkClient() {
    try {
        return (NetworkClient) getNetworkClientClass().getConstructors()[0].newInstance();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    return null;
}

How can I test (using unit testing) that newInstance() throw an InvocationTargetException (and the other exception) ?

I'm currently using Mockito and Hamcrest for the rest of the UT.

回答1:

Somewhere in your junit test you are creating an instance of the NetworkClient class. This should be in either the setUp() method (junt 3) or the @Before method (junit 4). Whereever that is, wrap the instance in a spy()

classToTest = spy(new NetworkClient());

If you are using the NetworkClient default constructor, just declare the field with the @Spy annotation and Mockito will create it for you as a spy.

@Spy private NetworkClient classToTest;

Be sure to call MockitoAnnotations.initMocks(this); in the @Before or setUp method for the annotation to work.

Once the classToTest field is a spy, you can mock out the getConstructors() class to return your test array and have the first constructor throw the desired exception.



回答2:

The simplest approach can be to create a static nested class that extends NetworkClient in your test class that will throw an Exception in its constructor like this:

public class MyTest {
    public static class MyFailingNetworkClient extends NetworkClient {
        public MyFailingNetworkClient() {
            throw new RuntimeException("Cannot create this object");
        }
    }
    ...
}

Then in your test case, you can use Mokito to make getNetworkClientClass() returns MyFailingNetworkClient.class (assuming that it cannot be done with a simple setter) as next:

MyObject object = spy(new MyObject());
when(object.getNetworkClientClass()).thenReturn(
    MyFailingNetworkClient.class
);