Как издеваться над System.exit с помощью PowerMockito? - PullRequest
0 голосов
/ 01 августа 2020

Я хочу выполнить модульный тест Java кода, который вызывает System.exit (-1), и хочу, чтобы он просто ничего не делал вместо выхода из процесса. Основная причина в том, что в противном случае JaCoCo не будет работать должным образом, и руководящие принципы проекта хотят, чтобы эта линия была закрыта. Изменение проверенного кода тоже не вариант. Остальные вызовы системы должны работать нормально. PowerMockito 2.0.7 уже используется в проекте, и его также следует использовать здесь. Моя текущая версия Java - 1.8.0_181 на Windows.

Я пробовал с

PowerMockito.spy(System.class);
PowerMockito.doNothing().when(System.class, "exit", ArgumentMatchers.any(int.class));
//here comes the code under test that calls System.exit

Кажется, это не работает, System.exit все равно завершает процесс. Как заставить это работать?

1 Ответ

1 голос
/ 01 августа 2020

Я думаю, вам следует заменить обе строки в образце кода

PowerMockito.spy(System.class);
PowerMockito.doNothing.....

на

PowerMockito.mockStatic(System.class);

Это изменение работает в моем локальном, поскольку System.exit ничего не делает из-за макета на методе stati c.

Кроме того, я надеюсь, что вы используете аннотацию PrepareForTest

@PrepareForTest(CLASS_UNDER_TEST)

Шпионский метод заключается в вызове реальных методов и наличии некоторой оболочки для нестандартных c методы. Поскольку вам нужен макет для методов stati c, вместо него следует использовать метод mockStati c.

Обновление 1

Метод mockStati c PowerMockito default создает макет для всех методов stati c в классе. У меня нет чистого решения. Но я могу предложить решение, которое выглядит некрасиво, но делает то, что нужно, т.е. только фиктивный метод c stati c, а остальные методы вызывают реальные методы. Метод mockStati c PoweMockito внутренне вызывает DefaultMockCreator для имитации методов stati c.

@RunWith(PowerMockRunner.class)
public class StaticTest {

  @Test
  public void testMethod() throws Exception {

    // Get static methods for which mock is needed
    Method exitMethod = System.class.getMethod("exit", int.class);
    Method[] methodsToMock = new Method[] {exitMethod};

    // Create mock for only those static methods
    DefaultMockCreator.mock(System.class, true, false, null, null, methodsToMock);

    System.exit(-1); // This will be mocked
    System.out.println(System.currentTimeMillis()); // This will call up real methods
  }
}

Согласно документации PowerMockito, правильный способ вызова метода stati c void -

PowerMockito.mockStatic(SomeClass.class);
PowerMockito.doNothing().when(SomeClass.class);
SomeClass.someVoidMethod();

Ссылка - https://github.com/powermock/powermock/wiki/Mockito#how -to-stub-void-stati c -method-to-throw-exception

Это должно создать имитацию поведения для Speci c stati c недействительный метод. К сожалению, это не работает для системного класса, потому что системный класс является окончательным. Если бы это не было окончательно, это сработало бы. Я попробовал и получил вот это исключение -

org.mockito.exceptions.base.MockitoException: 
Cannot mock/spy class java.lang.System
Mockito cannot mock/spy because :
 - final class

Код -

@Test
public void testMethod() throws Exception {
    PowerMockito.mockStatic(System.class);
    PowerMockito.doNothing().when(System.class);
    System.exit(-1); // mockito error coming here

    System.exit(-1);
    System.currentTimeMillis();
}
...