PowerMock + Mockito VS один только Mockito

Кто-нибудь может подвести итог, какие именно функции дает вам добавление PowerMock поверх Mockito?

Пока я нашел эти:

  • mock static, final и private методы
  • удалить статические инициализаторы
  • разрешить насмешку без внедрения зависимостей - мне это не ясно. Можете ли вы уточнить?

Добавляет ли это что-то еще? Не могли бы вы подвести итог в несколько строк?

И нужно ли чем-то жертвовать при использовании PowerMock?


person Vladislav Rastrusny    schedule 17.05.2011    source источник
comment
Отличным примером превосходства PowerMock над Mockito является ответ Mockito Spy - заглушка перед вызовом конструктора.   -  person Michael Osofsky    schedule 04.12.2014


Ответы (5)


Я не знаю других преимуществ навскидку, но я хочу ответить на 2 ваших подвопроса (и это слишком долго для комментария):

разрешить насмешку без внедрения зависимостей - мне это не ясно. Можете ли вы уточнить?

Я думаю, что это пришло из вики-страницы Motivation, где они описывают способ рефакторинга кода, чтобы не вызывать статические методы. чтобы сделать его тестируемым. В качестве конкретного примера того, к чему, я думаю, они пришли, допустим, у вас есть этот код, и вы хотите протестировать метод, имитирующий поведение статического метода, без использования powermock:

public class MyClass {
     public void doGetString() {
         ...
         OtherClass.getString(); //It's complex and scary and needs mocking!
         ...
     }
}

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

public class MyClass {
     public static class StringGetter {
         public getString() {
             return OtherClass.getString();                 
         }
     }

     private final StringGetter getter;

     //Existing Constructor
     public MyClass() {
         this(new StringGetter());
     }

     //DI Constructor
     MyClass(StringGetter getter) {
         this.getter = getter;
     }

     public void doGetString() {
         ...
         getter.getString();
         ...
     }
}

Я отделил поведение моего метода от поведения статического вызова и могу использовать конструктор DI для легкого внедрения моков во время тестирования. Конечно, с помощью powermock я мог бы просто смоделировать статический метод на месте и запустить его.

И нужно ли чем-то жертвовать при использовании PowerMock?

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

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

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

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

person Charlie    schedule 17.06.2011
comment
Я хотел бы резюмировать предостережение родителя об использовании PowerMock для версии tl;dr: предпочтительнее рефакторинг, когда это возможно/разрешено; наличие PowerMock может отговорить от рефакторинга - person Sled; 09.11.2011
comment
... вы эффективно тестируете разные классы, хотя и основанные на ваших существующих классах. Это также относится к фиктивным подклассам, созданным с помощью CGLIB, который сам использует пользовательский загрузчик классов; тестируемый класс не модифицируется напрямую, но вызовы имитируемых методов должны сначала пройти через переопределяющий метод, чей байт-код был создан динамически. Так что этот аргумент действительно слаб. Что касается аргумента костыля, я думаю, вы упускаете из виду другую сторону медали: наличие препятствий для использования final, new и static означает, что вам нужно пожертвовать некоторыми полезными вариантами дизайна. - person Rogério; 16.02.2012
comment
1) Похоже, вы предполагаете, что я расширяю тестируемый класс, чтобы проверить его? Хотя это действительно особенность Mockito, я бы сказал, что этот случай также вызывает запах кода (если я издеваюсь над частями своего класса, чтобы протестировать другие части, мое разделение проблем, вероятно, не очень хорошо). Теперь, что касается Mocked-объектов, которые я предоставляю своему тестируемому коду, меня не волнует, как они работают, пока они стабильны для моих тестов, мой тестируемый класс должен быть как можно ближе к производству. - person Charlie; 16.02.2012
comment
2) Я все еще придерживаюсь аргумента костыля. Ничто не мешает мне использовать final, new или static... но мое мнение заключается в том, что код в таких методах не должен требовать насмешек, если я решу их использовать. Если они настолько сложны или пронизаны побочными эффектами, мне, вероятно, следует подумать об инкапсуляции в другие объекты, чтобы я мог вводить макеты во время тестирования или при изменении реализации. (Не говоря уже о фреймворках DI, таких как Guice, @Inject — это новая новинка :D ) - person Charlie; 16.02.2012

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

person Premraj    schedule 09.08.2016

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

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

person avandeursen    schedule 07.03.2012

Еще одна особенность PowerMock заключается в том, что мы можем макетировать создание новых объектов в методе. Это полезно, когда мы не можем изменить код тестируемого метода.

person Caesar    schedule 07.10.2015

Для имитации финального класса мы можем использовать org.mockito.plugins.MockMaker. Что вам нужно сделать, это

  1. Создайте в своей папке test/resource папку с именемmockito-extensions.
  2. Создайте под ним файл с именем org.mockito.plugins.MockMaker.
  3. В этом файле всего одна строка mock-maker-inline

Это не потребует от вас добавления какой-либо новой библиотеки и, следовательно, экономии времени выполнения.

person Anuj Acharya    schedule 05.04.2019