Как проверить этот улов (исключение e), вызванный {e.printStackTrace ();} - PullRequest
0 голосов
/ 05 мая 2020

Мне нужно достичь 95% тестового покрытия (моя задача). У меня проблемы со следующим классом

    public class Context {

    public static <T> T getObject(Class<T> clazz) {
        Object bean = null;

        try {
            bean = clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return (T) bean;
    }

    private Context() {
    }
}

, чтобы достичь 95%. Мне нужно проверить, что e.printStackTrace(); вызывается при возникновении исключения. Я пробовал разные способы, но ни один из них не работает. Буду признателен за любую поддержку.

Ответы [ 2 ]

1 голос
/ 05 мая 2020

Чтобы проверить, что вызывается printStackTrace, самый простой способ, который я могу придумать, - это объект spy / mock Exception.

Используя mockito, вы можете передать имитацию Class, которая выдает spy Exception, когда вызывается newInstance.

Class<?> mockClass = mock(Class.class);
Exception e = Mockito.spy(new Exception());
Mockito.doThrow(e).when(mockClass).newInstance();

context.getObject(mockClass);

Mockito.verify(e).printStackTrace();

Вы также можете сделать что-нибудь с powermock и whenNew, если вы знаете, куда Exception будет брошен (чтобы вы могли @PrepareForTest этот класс).

Exception e = Mockito.spy(new Exception());
PowerMockito.whenNew(Exception.class).thenReturn(e);

context.getObject(SomeService.class);

Mockito.verify(e).printStackTrace();

Примечание: я не компилировал и не тестировал ни одно из вышеперечисленных (и постоянно получаю неправильные имена классов Mockito и PowerMockito по-разному).


Если вы настроены делать это без библиотеки, вы можете сделать что-то вроде:

  1. Создайте собственный тип Exception, который явно устанавливает некоторый флаг при вызове этого метода:
  2. Создайте собственный class, который выдает указанное выше Exception при вызове конструктора без аргументов.
  3. Передайте .class этого пользовательский класс в свой метод и убедитесь, что флаг установлен.

Что-то вроде:

class MyException extends Exception {
    public static boolean printStackTraceCalled = false;

    @Override
    public void printStackTrace() {
        MyException.printStackTraceCalled = true;
        super.printStackTrace();
    }
}

class MyClass {
    MyClass() {
        throw new MyException();
    }
}

@Test
void testThing() {
    context.getObject(MyClass.class);

    Assertions.assertTrue(MyException.printStackTraceCalled);
}

Тем не менее, это просто как вы бы это сделали ... Я не говорю, что это хорошая идея. Это плохой способ справиться с Exception s, и нацеливание на конкретное c% покрытие кода чаще всего бессмысленно.

0 голосов
/ 01 июня 2020

Вот как я решил эту проблему. Я немного реорганизовал код:

 private static final Logger LOGGER = Logger.getLogger(Context.class.getName());

    public <T> T getObject(Class<T> clazz) {
        T bean = null;

        try {
            bean = clazz.getConstructor().newInstance();
        } catch (Exception e) {
            LOGGER.log(Level.INFO, e, () -> "Exception occurred during Context usage whilst created " + clazz.getName());
        }
        return bean;
    }

и вот он тест:

    @Test
    void getObject_ShouldThrowException() throws Exception {
        Exception mockedException = mock(InstantiationException.class);
        Logger mockedLogger = mock(Logger.class);

        class Dummy {

            public Dummy() throws Exception {
                throw mockedException;
            }
        }

        try {
            Dummy dummy = context.getObject(Dummy.class);
        } catch (Exception e) {
            verify(mockedLogger, times(1)).log(Level.INFO, anyString());
        }
    }
...