@RunWith(PowerMockRunner.class) vs @RunWith (MockitoJUnitRunner.class)

В обычном насмешке с аннотациями @Mock и @InjectMocks тестируемый класс должен запускаться с @RunWith(MockitoJUnitRunner.class).

@RunWith(MockitoJUnitRunner.class)
public class ReportServiceImplTestMockito {

     @Mock 
     private TaskService      mockTaskService;

     @InjectMocks 
     private ReportServiceImpl service;

         // Some tests
}

но в некотором примере я использую @RunWith(PowerMockRunner.class):

@RunWith(PowerMockRunner.class)
public class Tests {
  @Mock
  private ISomething mockedSomething;

  @Test
  public void test1() {
    // Is the value of mockedSomething here
  }

  @Test
  public void test2() {
    // Is a new value of mockedSomething here
  }
}

мог ли кто-нибудь указать, в чем разница, и когда я хочу использовать один вместо другого?

Ответ 1

На первый взгляд, ответ прост: ну, есть несколько насмешливых фреймворков, и есть разные способы их использования.

Первый пример говорит JUnit использовать "модуль модульного тестирования", который предоставляет среда Mockito Mocking. Во втором примере используется модуль модульного тестирования из среды PowerMock.

Чтобы все было понятно, у вас также должны быть разные операторы импорта, так как обе платформы имеют разные реализации, например, для аннотации @Mock.

(основной смысл использования этих специфичных для фреймворка тестов заключается в том, что они заботятся об инициализации всех полей специальными аннотациями, специфичными для фреймворка).

Итак, разница здесь просто в том, что первый пример написан с использованием инфраструктуры Mockito, а второй использует PowerMock.

Теперь, какой из них использовать?

Ответ: Мокито.

Зачем? Какая-то уродливая правда в том, что PowerMock-one - это крик о помощи. Там написано, что "тестируемый класс плохо спроектирован, пожалуйста, исправьте его".

Значение: как разработчик, вы можете написать "простой для тестирования" код или "сложный для тестирования" код. Многие люди делают второе: они пишут код, который сложно протестировать. А затем PowerMock (ito) предоставляет средства для тестирования этого кода.

PowerMock (ito) дает вам возможность имитировать (таким образом контролировать) вызовы статических методов и new(). Чтобы включить это, PowerMock (ito) манипулирует байтовым кодом тестируемого кода. Это отлично подходит для небольших баз кода, но когда вы сталкиваетесь с миллионами строк производственного кода и тысячами модульных тестов, все совершенно иначе. Я видел, что многие тесты PowerMock провалились без видимой причины, спустя несколько часов, чтобы выяснить, что какая-то "статическая" вещь где-то еще была изменена, и это как-то влияет на другой статический/новый управляемый тестовый пример PowerMock.

В какой-то момент наша команда приняла осознанное решение: когда вы пишете новый код, и вы можете проверить это только с PowerMock... это неприемлемо. С тех пор мы создаем только тестовые наборы Mockito, и с тех пор ни разу у нас не было странных проблем, которые мешали нам с PowerMock.

Единственная приемлемая причина использовать PowerMock - это когда вы хотите протестировать существующий (возможно, сторонний) код, который вы не хотите изменять. Но, конечно, какой смысл тестировать такой код? Если вы не можете изменить этот код, почему тесты должны внезапно проваливаться?

Ответ 2

PowerMock никогда не должен быть вашим первым выбором. Если вы только что написали класс, который можно тестировать только с PowerMock, вы сделали что-то не так. Класс должен иметь внедрение зависимостей или конструктор с зависимостями, поэтому тестирование облегчается и, конечно, не пытайтесь использовать статические методы, так как они не являются поддельными в обычных средах (читай: mockito).

С другой стороны: если у вас большой проект и вы хотите добавить в него модульные тесты, потому что предыдущий разработчик этого не делал, PowerMock может быть единственным решением без полного рефакторинга всего. И с этой точки зрения я предпочитаю PowerMock выше никаких тестов вообще.

PowerMock грязный, так как он изменяет байт-код, и покрытие кода с помощью JaCoCo (бегунка покрытия SonarQube) не работает, но бегунок покрытия кода IntelliJ работает с PowerMock.

Когда в одном классе один метод не может быть протестирован с Mockito, я разделяю тест: один тестовый класс с Mockito и один тестовый класс с PowerMock. Это обеспечит лучшее покрытие кода в SonarQube.

public class ClassToTest {

    public void testableMethod() {
        /* Do something */
    }

    public String methodWithStaticCall() {
        return MyTest.staticMethod();
    }
}

Тогда у меня есть один класс для тестирования первого метода:

@RunWith(MockitoJUnitRunner.class)
public class testClassToTest() {
   private sut = new ClassToTest();

   @Test
   public testMethod() {
       sut.testableMethod();
   }
}

И один с PowerMock:

@RunWith(PowerMockJUnitRunner.class)
@PrepareForTest({MyTest.class, ClassToTest.class})
public class testClassToTestPM() {
   private sut = new ClassToTest();

   @Before
   public void before() {
       mockStatic(MyTest.class);
   }

   @Test
   public testMethod() {
       mockStatic(MyTest.class);
       when(MyTest.staticMethod()).thenReturn("test");
       assertEquals("test", sut.methodWithStaticCall());
   }
}

Ответ 3

PowerMock позволяет вам имитировать статические и частные методы, а также конечные классы и многое другое.

PowerMock - это среда, которая расширяет другие макетные библиотеки, такие как EasyMock с более мощными возможностями. PowerMock использует classloader и байт-код, чтобы включить насмешку статических методы, конструкторы, конечные классы и методы, частные методы, удаление статических инициализаторов и многое другое.

Может быть некоторый запах кода , если вам нужно издеваться над этими типами компонентов, , но может быть полезно. В какой-то момент вы можете работать в устаревшем проекте, который создал статические вспомогательные классы, у которых есть зависимости, которые нужно издеваться. Если у вас есть возможность изменить архитектуру, исправить дизайн! В противном случае используйте правильную технологию для своих тестов.

Если вам не нужно издеваться над статическими или частными функциями, вам не нужно использовать PowerMock. PowerMock - обертка вокруг других насмешливых фреймворков.