Въведение в PowerMock

1. Общ преглед

Единичното тестване с помощта на подигравателна рамка е признато за полезна практика от дълго време, и по-специално Mockito рамката доминира на този пазар през последните години.

И за да се улеснят приличните дизайни на кодове и да се направи публичен API прост, някои желани функции умишлено са пропуснати. В някои случаи обаче тези недостатъци принуждават тестерите да пишат тромав код, само за да направят създаването на макети възможно.

Тук влиза в сила рамката PowerMock.

PowerMockito е разширителен API на PowerMock за поддръжка на Mockito. Той предоставя възможности за работа с Java Reflection API по прост начин за преодоляване на проблемите на Mockito, като липсата на способност за подигравка на крайни, статични или частни методи.

Този урок ще даде въведение в PowerMockito API и как се прилага в тестовете.

2. Подготовка за тестване с PowerMockito

Първата стъпка за интегриране на поддръжката на PowerMock за Mockito е да включите следните две зависимости във файла Maven POM:

 org.powermock powermock-module-junit4 1.6.4 test   org.powermock powermock-api-mockito 1.6.4 test 

След това трябва да подготвим нашите тестови случаи за работа с PowerMockito, като приложим следните две анотации:

@RunWith(PowerMockRunner.class) @PrepareForTest(fullyQualifiedNames = "com.baeldung.powermockito.introduction.*")

Елементът fullQualifiedNames в анотацията @PrepareForTest представлява масив от напълно квалифицирани имена на типове, които искаме да подиграем. В този случай използваме име на пакет с заместващ символ, за да кажем на PowerMockito да подготви всички типове в пакета com.baeldung.powermockito.introduction за подигравка.

Сега сме готови да използваме силата на PowerMockito .

3. Подигравателни конструктори и крайни методи

В този раздел ще демонстрираме начините за получаване на фалшив екземпляр вместо реален при инстанциране на клас с новия оператор и след това ще използваме този обект, за да се подиграем на окончателен метод. Класът на сътрудничество, чиито конструктори и крайни методи ще бъдат подигравани, се дефинира както следва:

public class CollaboratorWithFinalMethods { public final String helloMethod() { return "Hello World!"; } }

Първо, създаваме фиктивен обект, използвайки PowerMockito API:

CollaboratorWithFinalMethods mock = mock(CollaboratorWithFinalMethods.class);

След това задайте очакване, казвайки, че всеки път, когато бъде извикан конструкторът no-arg от този клас, трябва да се върне фалшив екземпляр, а не реален:

whenNew(CollaboratorWithFinalMethods.class).withNoArguments().thenReturn(mock);

Нека да видим как това подиграване на конструкцията работи в действие чрез създаване на инстанция на класа CollaboratorWithFinalMethods с помощта на конструктора по подразбиране и след това да проверим поведението на PowerMock:

CollaboratorWithFinalMethods collaborator = new CollaboratorWithFinalMethods(); verifyNew(CollaboratorWithFinalMethods.class).withNoArguments();

В следващата стъпка се задава очакване на крайния метод:

when(collaborator.helloMethod()).thenReturn("Hello Baeldung!");

След това се изпълнява този метод:

String welcome = collaborator.helloMethod();

Следните твърдения потвърждават, че методът helloMethod е бил извикан за обекта на сътрудник и връща стойността, зададена от подигравателното очакване:

Mockito.verify(collaborator).helloMethod(); assertEquals("Hello Baeldung!", welcome);

Ако искаме да се подиграем на конкретен краен метод, а не на всички окончателни в обекта, методът Mockito.spy (T обект) може да бъде полезен. Това е илюстрирано в раздел 5.

4. Подигравателни статични методи

Да предположим, че искаме да се подиграваме със статични методи на клас с име CollaboratorWithStaticMethods. Този клас се декларира, както следва:

public class CollaboratorWithStaticMethods { public static String firstMethod(String name) { return "Hello " + name + " !"; } public static String secondMethod() { return "Hello no one!"; } public static String thirdMethod() { return "Hello no one again!"; } }

За да се подиграем с тези статични методи, трябва да регистрираме заграждащия клас с PowerMockito API:

mockStatic(CollaboratorWithStaticMethods.class);

Като алтернатива можем да използваме метода Mockito.spy (клас клас) , за да се подиграем на специфичен, както е показано в следващия раздел.

След това могат да се зададат очаквания за определяне на стойностите, които методите трябва да връщат при извикване:

when(CollaboratorWithStaticMethods.firstMethod(Mockito.anyString())) .thenReturn("Hello Baeldung!"); when(CollaboratorWithStaticMethods.secondMethod()).thenReturn("Nothing special");

Или може да се зададе изключение, което да се хвърля при извикване на метода thirdMethod :

doThrow(new RuntimeException()).when(CollaboratorWithStaticMethods.class); CollaboratorWithStaticMethods.thirdMethod();

Сега е време за изпълнение на първите два метода:

String firstWelcome = CollaboratorWithStaticMethods.firstMethod("Whoever"); String secondWelcome = CollaboratorWithStaticMethods.firstMethod("Whatever");

Вместо да извикват членове на реалния клас, горните извиквания се делегират на методите на макета. Следните твърдения доказват, че макетът е влязъл в сила:

assertEquals("Hello Baeldung!", firstWelcome); assertEquals("Hello Baeldung!", secondWelcome);

Също така сме в състояние да проверим поведението на макетните методи, включително колко пъти е извикан метод. В този случай firstMethod е бил извикан два пъти, докато secondMethod никога:

verifyStatic(Mockito.times(2)); CollaboratorWithStaticMethods.firstMethod(Mockito.anyString()); verifyStatic(Mockito.never()); CollaboratorWithStaticMethods.secondMethod();

Забележка: Методът verifyStatic трябва да бъде извикан точно преди всяка проверка на статичен метод за PowerMockito, за да се знае, че последователното извикване на метод е това, което трябва да бъде проверено.

И накрая, статичният метод thirdMethod трябва да хвърли RuntimeException, както е декларирано в макета преди. Той се потвърждава от очаквания елемент на анотацията @Test :

@Test(expected = RuntimeException.class) public void givenStaticMethods_whenUsingPowerMockito_thenCorrect() { // other methods CollaboratorWithStaticMethods.thirdMethod(); }

5. Частично подигравка

Вместо да се подиграва с цял клас, PowerMockito API позволява да се подиграва с част от него, използвайки шпионския метод. Следният клас ще бъде използван като сътрудник, за да илюстрира поддръжката на PowerMock за частично подиграване:

public class CollaboratorForPartialMocking { public static String staticMethod() { return "Hello Baeldung!"; } public final String finalMethod() { return "Hello Baeldung!"; } private String privateMethod() { return "Hello Baeldung!"; } public String privateMethodCaller() { return privateMethod() + " Welcome to the Java world."; } }

Нека започнем с подигравка със статичен метод, който се нарича staticMethod в горната дефиниция на клас. Първо, използвайте PowerMockito API, за да се подигравате частично с класа CollaboratorForPartialMocking и задайте очакване за неговия статичен метод:

spy(CollaboratorForPartialMocking.class); when(CollaboratorForPartialMocking.staticMethod()).thenReturn("I am a static mock method.");

След това се изпълнява статичният метод:

returnValue = CollaboratorForPartialMocking.staticMethod();

Подигравателното поведение се проверява по следния начин:

verifyStatic(); CollaboratorForPartialMocking.staticMethod();

Следващото твърдение потвърждава, че действително е бил извикан методът на макет чрез сравняване на връщаната стойност с очакването:

assertEquals("I am a static mock method.", returnValue);

Сега е време да преминем към крайния и частния метод. За да илюстрираме частичното подиграване на тези методи, трябва да създадем екземпляр на класа и да кажем на API на PowerMockito да го шпионира :

CollaboratorForPartialMocking collaborator = new CollaboratorForPartialMocking(); CollaboratorForPartialMocking mock = spy(collaborator);

The objects created above are used to demonstrating the mocking of both the final and private methods. We will deal with the final method now by setting an expectation and invoke the method:

when(mock.finalMethod()).thenReturn("I am a final mock method."); returnValue = mock.finalMethod();

The behavior of partially mocking that method is proved:

Mockito.verify(mock).finalMethod();

A test verifies that calling the finalMethod method will return a value that matches the expectation:

assertEquals("I am a final mock method.", returnValue);

A similar process is applied to the private method. The main difference is that we cannot directly invoke this method from the test case. Basically, a private method is to be called by other ones from the same class. In the CollaboratorForPartialMocking class, the privateMethod method is to be invoked by the privateMethodCaller method and we will use the latter as a delegate. Let's start with the expectation and invocation:

when(mock, "privateMethod").thenReturn("I am a private mock method."); returnValue = mock.privateMethodCaller();

The mocking of the private method is confirmed:

verifyPrivate(mock).invoke("privateMethod");

The following test makes sure that the return value from invocation of the private method is the same as the expectation:

assertEquals("I am a private mock method. Welcome to the Java world.", returnValue);

6. Conclusion

Този урок е предоставил въведение в PowerMockito API, демонстрирайки използването му при решаване на някои от проблемите, с които се сблъскват разработчиците при използване на Mockito framework.

Внедряването на тези примери и кодови фрагменти може да бъде намерено в свързания проект GitHub.