С ним (powermock) больше не беспокойтесь о некачественных юнит-тестах

Mockito

Зачем писать модульные тесты

  • Преимущества: Модульный тест может снизить количество ошибок и повысить качество кода. Вы также можете ознакомиться со своим бизнесом с помощью модульного тестирования.
  • Компания Устойчивые требования: Некоторые компании могут также потребовать, чтобы каждый раз был добавлен код, или какой процент охвата тестового устройства кода должен быть изменен до подачи заявки на запрос слияния кода.

Какой фреймворк модульного тестирования выбрать

В настоящее время обычно используются инструменты модульного тестирования Java junit4+Mock (Mockito, jmock, EasyMock, powermock). Почему стоит выбрать powermock? При выполнении модульного тестирования мы обнаружим, что метод, который мы хотим протестировать, будет иметь много внешне зависимых объектов или некоторых других служебных вызовов, таких как (отправка почты, сетевое взаимодействие, вызовы soa). И мы не имеем никакого контроля над этими внешне зависимыми объектами. Чтобы решить эту проблему, нам нужно использовать Mock для имитации этих внешне зависимых объектов и управления ими. Заботьтесь только о том, верна ли наша собственная бизнес-логика. В это время работает powermock.Он может не только имитировать внешние зависимости, но также имитировать приватные методы и финальные методы.Короче говоря, его функции очень мощные.

что такое powermocker

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

Общие примечания

  • @RunWith(PowerMockRunner.класс) Скажите JUnit использовать PowerMockRunner для тестирования
  • @Preparefortest ({DEMODAO.CLASS}) Все столбцы, которые необходимо протестировать здесь, подходят для моделирования класса Final или классов методов Final, Private, Static, Native.
  • @PowerMockIgnore({"javax.management.", "javax.net.ssl."}) Чтобы решить проблему с ошибкой загрузчика классов после использования powermock
  • @SuppressStaticInitializationFor Не позволяйте статическому коду загружаться Другие дополнительные аннотации могут относиться к:GitHub.com/power mock/afraid…

С чего начать

JUnit 4.4 и выше
<properties>
    <powermock.version>2.0.2</powermock.version>
</properties>
<dependencies>
   <dependency>
      <groupId>org.powermock</groupId>
      <artifactId>powermock-module-junit4</artifactId>
      <version>${powermock.version}</version>
      <scope>test</scope>
   </dependency>
   <dependency>
      <groupId>org.powermock</groupId>
      <artifactId>powermock-api-mockito2</artifactId>
      <version>${powermock.version}</version>
      <scope>test</scope>
   </dependency>
</dependencies>

пример PowerMock

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

/**
 *
 * @Date: 2020/3/31
 * @Description:
 */
@Repository
public class DemoDao {
    public String mockPublicMethod(String type) throws Throwable {
        throw  new Throwable();
    }
    public final String mockFinalMethod(String type) throws Throwable {
        throw  new Throwable();
    }
    public static String mockStaticMethod(String type) throws Throwable {
        throw  new Throwable();
    }
}
/**
 * @Date: 2020/3/31 11:34
 * @Description:
 */
@Component
public class DemoService extends AbstractDemo{

    @Autowired
    private DemoDao demoDao;

    public String mockPublicMethod() throws Throwable {
        return demoDao.mockPublicMethod("demo");
    }

    public String mockFinalMethod() throws Throwable {
        return demoDao.mockFinalMethod("demo");
    }

    public String mockStaticMethod() throws Throwable {
        return DemoDao.mockStaticMethod("demo");
    }


    private String callPrivateMethod(String type) {
        return type;
    }

    public String mockPublicMethodCallPrivateMethod(String type) throws Throwable {
        return callPrivateMethodThrowable(type);
    }

    private String callPrivateMethodThrowable(String type) throws Throwable {
        throw new Throwable();
    }

    public String mockExtendMethod(String type) throws Throwable {
       return getExtendMethod();
    }

    public static String UUID = "uuid";
}

издеваться над обычным общедоступным методом
   /**
    * @Date: 2020/4/24 14:22
    * @Description:
    */
   @RunWith(PowerMockRunner.class)
   public class DemoServiceTest {
   
       @InjectMocks
       private DemoService demoService;
       @Mock
       private DemoDao demoDao;
       
    /**
    * mock 普通方法
    * @throws Throwable
    */
       @Test
       public void mockPublicMethod() throws Throwable {
           String type = UUID.randomUUID().toString();
           PowerMockito.when(demoDao.mockPublicMethod(any())).thenReturn(type);
           String result = demoService.mockPublicMethod();
           Assert.assertEquals(type, result);
       }
фиктивный окончательный метод

Это то же самое, что и обычный метод, с той лишь разницей, что в класс необходимо добавить аннотацию PrepareForTest.

    @RunWith(PowerMockRunner.class)
    @PrepareForTest(DemoDao.class)
    public class DemoServiceTest {
    
        @InjectMocks
        private DemoService demoService;
        @Mock
        private DemoDao demoDao;
    
       
      /**
          * mock final方法
          * @throws Throwable
          */
         @Test
         public void mockFinalMethod() throws Throwable {
             String type = UUID.randomUUID().toString();
             PowerMockito.when(demoDao.mockFinalMethod(any())).thenReturn(type);
             String result = demoService.mockFinalMethod();
             Assert.assertEquals(type, result);
         }
  
Имитация статического метода (с использованием PowerMockito.mockStatic) также украшена аннотацией PrepareForTest.
  @RunWith(PowerMockRunner.class)
  @PrepareForTest(DemoDao.class)
  public class DemoServiceTest {
  
      @InjectMocks
      private DemoService demoService;
      @Mock
      private DemoDao demoDao;
      /**
       * mock 静态方法
       * @throws Throwable
       */
      @Test
      public void mockStaticMethod() throws Throwable {
          String type = UUID.randomUUID().toString();
          PowerMockito.mockStatic(DemoDao.class);
          PowerMockito.when(DemoDao.mockStaticMethod(any())).thenReturn(type);
          String result = demoService.mockStaticMethod();
          Assert.assertEquals(type, result);
      }
вызывать приватные методы
    /**
     * 调用私有方法
     * 
     * @throws Throwable
     */
     /**
        * 调用私有方法
        * 
        * @throws Throwable
        */
       @Test
       public void callPrivateMethod() throws Throwable {
           // 第一种方式
           String type = UUID.randomUUID().toString();
           Method method = PowerMockito.method(DemoService.class, "callPrivateMethod", String.class);
           String result = (String) method.invoke(demoService, type);
           Assert.assertEquals(type, result);
   
           //第二种方式
           String result1 = Whitebox.invokeMethod(demoService, "callPrivateMethod", type);
           Assert.assertEquals(type, result1);
       }
Поддельный закрытый метод (поддельный класс также должен быть украшен аннотацией PrepareForTest.)
    /**
     * mock私有方法
     *
     * @throws Throwable
     */
    @Test
    public void mockPrivateMethod() throws Throwable {
        String type = UUID.randomUUID().toString();
        // 重点这一句
        demoService = PowerMockito.spy(demoService);
        PowerMockito.doReturn(type).when(demoService,"callPrivateMethodThrowable",type);
        String result = demoService.mockPublicMethodCallPrivateMethod(type);
        Assert.assertEquals(type, result);
    }
фиктивный родительский метод
     /**
       * mock父类方法
       *
       * @throws Throwable
       */
      @Test
      public void mockExtendMethod() throws Throwable {
          String type = UUID.randomUUID().toString();
          // 需要mock的父类的方法
          Method method = PowerMockito.method(AbstractDemo.class, "getExtendMethod");
          // InvocationHandler
          PowerMockito.replace(method).with((proxy, method1, args) -> type);
          String result = demoService.mockExtendMethod(type);
          Assert.assertEquals(type, result);
      }
фиктивный конструктор
     public DemoService() {
            throw new NullPointerException();
        }
    @Test
    public void mockConstructorMethod() throws Throwable {
        PowerMockito.whenNew(DemoService.class).withNoArguments().thenReturn(demoService);
    }
имитация поля
        /**
         * mock 字段
         */
        @Test
        public void mockFiled(){
            String uuid = UUID.randomUUID().toString();
            Whitebox.setInternalState(DemoService.class, "UUID",uuid);
            Assert.assertEquals(DemoService.UUID, uuid);
        }

конец

  • Из-за моего недостатка знаний и знаний неизбежно будут ошибки.Если вы обнаружите какие-либо ошибки, пожалуйста, оставьте сообщение и укажите на них мне, и я их исправлю.
  • Если вы считаете, что статья неплохая, ваша пересылка, обмен, оценка, лайки и комментарии будут для меня самой большой поддержкой.
  • Спасибо за прочтение, вам очень рады и ценим ваше внимание.
    在这里插入图片描述