Несмотря на то, что для платформы Java доступно множество библиотек макетов, лишь немногие из этих изящных платформ способны насмехаться над модификаторами static
и final
не поддерживающими mock-friendly. Статические (или классовые) методы, хотя и удобны для фабрик, становятся неприятностью для фреймворка, такого как Mockito , однако, с включением PowerMock , вы получаете себе пресловутый молот.
Как я уже писал ранее , мне приходилось иметь дело со сторонней библиотекой, которая используется для интеграции с сетевым сервисом. Эта библиотека, по сути, жестко связана с homebase, что, естественно, создает некоторые проблемы при попытке протестировать код, основанный на этой библиотеке. Кроме того, указанная библиотека содержала static
метод для создания экземпляров специализированного класса, от которого, естественно, зависел мой код.
PowerMock предназначен для совместной работы с EasyMock или Mockito ; более того, он поставляется с пользовательским бегуном для включения в JUnit . Я собираюсь показать вам, как использовать PowerMock с Mockito, так как мне кажется, что синтаксис Mockito гораздо более свободный, чем у EasyMock.
Для начала вам нужно использовать две аннотации на уровне класса — @RunWith
для указания класса PowerMockRunner
(это аннотация JUnit) и другую @PrepareForTest
, которая принимает класс со static
методами, которые вы хотите смоделировать. @PrepareForTest
предоставляется PowerMock.
В моем случае класс, содержащий static
метод, называется QTP
; мой тестовый класс выглядит так:
1
2
3
4
5
6
|
@RunWith (PowerMockRunner. class ) @PrepareForTest (QTP. class ) public class CreateCommandTest { @Test public void testCreateRequest() throws Exception {} } |
Далее, в вашем тестовом методе вы используете PowerMokito
mockStatic
, который принимает класс (снова) со статическими методами, которые вы хотите смоделировать.
1
2
3
4
5
|
@Test public void testCreateRequest() throws Exception { PowerMockito.mockStatic(QTP. class ); //.... } |
Затем вы можете mockStatic
статический метод для класса, который вы передаете, в mockStatic
и аннотацию @PrepareForTest
как вы обычно делаете с Mockito. Например, я могу использовать метод when
чтобы указать, что я хочу получить, когда вызывается этот статический метод.
01
02
03
04
05
06
07
08
09
10
|
@Test public void testCreateRequest() throws Exception { PowerMockito.mockStatic(QTP. class ); QTP qtpThing = mock(QTP. class ); //normal Mockito mocking //QTP.create is static when(QTP.create( "dm2q" , "0C4F7501UDC8C1EB43B06C988" )).thenReturn(qtpThing); //QTP.createRecord isn't static when(qtpThing.createRecord(any(Tckt. class ))).thenReturn( new Long(1000000L)); //... } |
Наконец, вы можете использовать PowerMock, чтобы убедиться, что ваш смоделированный статический метод действительно вызван. Требования здесь немного прикольные; то есть требуется сначала указать, сколько раз одной строкой кода, а затем фактически вызвать статический метод .
1
2
3
4
5
6
7
|
@Test public void testCreateRequest() throws Exception { //... PowerMockito.verifyStatic(Mockito.times( 1 )); QTP.create( "dm2q" , "0C4F7501UDC8C1EB43B06C988" ); //... } |
Да, это немного сбивает с толку, я знаю.
Тем не менее, как многие люди в мире Java давно поняли, статические методы несколько сложны, когда дело доходит до тестирования . То есть, хотя метод, который концептуально не имеет состояния, на первый взгляд кажется достаточно простым для тестирования, проблемы возникают, когда этот статический метод выполняет что-то вроде попадания в базу данных или, в моем случае, вызывает веб-сервис для сетевого актива. Нет простого способа переопределить такое поведение (если, конечно, вы не вытащите молоток).
Статические методы имеют место. Но когда дело доходит до тестирования кода, будь то устаревшая или какая-либо сторонняя библиотека, модификатор static
требует молотка, и, как я надеюсь, я вам показал, PowerMock — это тот молоток.