mocking private static
Вивчіть знущання над методами Private, Static та Void у Mockito на прикладах:
У цій серії практичних Підручники з Mockito , ми подивились різні типи Mockito Matchers в останньому уроці.
Взагалі кажучи, знущання над приватними та статичними методами підпадають під категорію незвичного знущання.
Якщо виникає необхідність знущатися над приватними та статичними методами / класами, це вказує на погано реконструйований код і насправді не перевіряється код, і, швидше за все, це якийсь застарілий код, який раніше не був дуже зручним для модульного тестування.
Сказавши це, все ще існує підтримка знущань над приватними та статичними методами кількома модулями модульного тестування, такими як PowerMockito (а не безпосередньо Mockito).
Знущання над методами “void” є загальними, оскільки можуть існувати методи, які по суті нічого не повертають, наприклад, оновлення рядка бази даних (розгляньте це як операцію PUT кінцевої точки API Rest, яка приймає вхідні дані і не повертає жодного результату).
Mockito надає повну підтримку знущань над методами порожнеч, що ми побачимо на прикладах у цій статті.
основні запитання та відповіді на інтерв’ю для sql
Що ви дізнаєтесь:
- Powermock - короткий вступ
- Знущання над приватними методами
- Знущальні статичні методи
- Знущальні методи порожнечі
- Поради та підказки
- Висновок
- Рекомендована література
Powermock - Короткий вступ
Для Mockito немає прямої підтримки знущань над приватними та статичними методами. Для тестування приватних методів вам потрібно буде рефакторинг коду щоб змінити доступ до захищеного (або пакета), і вам доведеться уникати статичних / кінцевих методів.
На мою думку, Mockito навмисно не забезпечує підтримку таких видів макетів, оскільки використання таких типів конструкцій коду є запахом коду та погано розробленим кодом.
Але є рамки, які підтримують знущання над приватними та статичними методами.
Powermock розширює можливості інших фреймворків, таких як EasyMock та Mockito, та надає можливість знущатися зі статичних та приватних методів.
# 1) Як: Powermock робить це за допомогою користувальницьких маніпуляцій з байт-кодом, щоб підтримувати знущання над приватними та статичними методами, кінцевими класами, конструкторами тощо.
# 2) Підтримувані пакети: Powermock надає 2 API розширення - один для Mockito та один для easyMock. Для цієї статті ми будемо писати приклади з розширенням Mockito для Power Mock.
# 3) Синтаксис :Powermockito має майже подібний синтаксис, як Mockito, за винятком деяких додаткових методів для знущань над статичними та приватними методами.
# 4) Налаштування Powermockito
Для того, щоб включити бібліотеку Mockito до проектів на основі gradle, нижче наведено бібліотеки, які слід включити:
testCompile group: 'org.powermock', name: 'powermock-api-mockito2', version: '1.7.4' testCompile group: 'org.powermock', name: 'powermock-module-junit4', version: '1.7.4'
Подібні залежності доступні і для maven.
Powermock-api-mockito2 - Бібліотека повинна включати розширення Mockito для Powermockito.
Powermock-module-junit4 - Модуль повинен містити PowerMockRunner (це спеціальний бігун, який буде використовуватися для запуску тестів з PowerMockito).
Важливим моментом тут є те, що PowerMock не підтримує тестовий бігун Junit5. Отже, тести потрібно писати проти Junit4, а тести потрібно виконувати за допомогою PowerMockRunner.
Щоб використовувати PowerMockRunner - тестовий клас потрібно помітити @RunWith (PowerMockRunner.class)
Тепер давайте обговоримо, знущаючись над приватними, статичними та недійсними методами в деталях!
Знущання над приватними методами
Знущання над приватними методами, які викликаються внутрішньо з тестованого методу, може бути неминучим у певний час. За допомогою powermockito це можливо, і перевірка здійснюється за допомогою нового методу під назвою ‘verifyPrivate’
Давай візьмемо anПриклад де тестований метод викликає приватний метод (який повертає логічне значення). Для того, щоб заглушити цей метод, щоб повернути true / false в залежності від тесту, слід встановити заглушку для цього класу.
У цьому прикладі тестований клас створюється як екземпляр шпигуна з глузуванням над кількома викликами інтерфейсу та викликом приватного методу.
Важливі моменти щодо Mock Private Method:
# 1) Метод тестування або клас тестування повинні бути позначені @ Підготовка до тесту (ClassUnderTest). Ця анотація повідомляє powerMockito підготувати певні класи до тестування.
Це будуть переважно ті класи, якими потрібно бути Маніпулюється байт-кодом . Зазвичай для підсумкових класів, класи, що містять приватні та / або статичні методи, над якими потрібно знущатися під час тестування.
Приклад:
@PrepareForTest(PriceCalculator.class)
# два) Щоб налаштувати заглушку на приватний метод.
Синтаксис - коли (примірник або шпигунський екземпляр, “privateMethodName”). thenReturn (// повертається значення)
Приклад:
when (priceCalculatorSpy, 'isCustomerAnonymous').thenReturn(false);
# 3) Щоб перевірити затуплений приватний метод.
Синтаксис - verifyPrivate (mockedInstance) .invoke (“privateMethodName”)
Приклад:
verifyPrivate (priceCalculator).invoke('isCustomerAnonymous');
Повний зразок тесту: Продовжуючи той самий приклад з попередніх статей, де priceCalculator має деякі висміювані залежності, такі як itemService, userService тощо.
Ми створили новий метод з назвою - calcuPriceWithPrivateMethod, який викликає приватний метод всередині того ж класу і повертає, анонімний клієнт чи ні.
@Test @PrepareForTest(PriceCalculator.class) public void calculatePriceForAnonymous_witStubbedPrivateMethod_returnsCorrectPrice() throws Exception { // Arrange ItemSku item1 = new ItemSku(); item1.setApplicableDiscount(5.00); item1.setPrice(100.00); double expectedPrice = 90.00; // Setting up stubbed responses using mocks when(priceCalculatorSpy, 'isCustomerAnonymous').thenReturn(false); when(mockedItemService.getItemDetails(123)).thenReturn(item1); // Act double actualDiscountedPrice = priceCalculatorSpy.calculatePriceWithPrivateMethod(123); // Assert verifyPrivate(priceCalculator).invoke('isCustomerAnonymous'); assertEquals(expectedPrice, actualDiscountedPrice); }
Знущальні статичні методи
Статичні методи можна знущатись подібним чином, як ми бачили для приватних методів.
Коли тестований метод передбачає використання статичного методу з того ж класу (або з іншого класу), нам потрібно буде включити цей клас до анотації PrepaForTest перед тестом (або тестового класу).
Важливі моменти щодо макетних статичних методів:
# 1) Метод тестування або клас тестування повинні бути позначені @ Підготовка до тесту (ClassUnderTest). Подібно до знущань над приватними методами / класами, це потрібно і для статичних класів.
# два) Одним додатковим кроком, необхідним для статичних методів, є - mockStatic (// назва статичного класу)
Приклад:
mockStatic(DiscountCategoryFinder.class)
# 3) Налаштування заглушки на статичний метод - це так само добре, як затухання будь-якого методу на будь-якому іншому примірнику інтерфейсу / класу.
Наприклад: Щоб заглушити getDiscountCategory () (який повертає перерахований DiscountCategory зі значеннями PREMIUM & GENERAL) статичний метод класу DiscountCategoryFinder, просто заглушіть наступним чином:
when (DiscountCategoryFinder. getDiscountCategory ()).thenReturn(DiscountCategory. PREMIUM );
# 4) Для перевірки макетної установки остаточного / статичного методу можна використовувати метод verifyStatic ().
Приклад:
verifyStatic (DiscountCategoryFinder.class, times (1));
Знущальні методи порожнечі
Давайте спершу спробуємо зрозуміти, які випадки використання можуть включати глухі методи порожнечі:
# 1) Наприклад, виклики методів - які надсилають повідомлення електронною поштою під час процесу.
Наприклад :Припустимо, ви змінили свій пароль для свого рахунку в Інтернет-банку, як тільки зміна буде успішною, ви отримаєте повідомлення на свою електронну пошту.
Це можна сприймати як / changePassword як виклик POST до API Банку, який включає виклик методу void для надсилання сповіщення клієнту електронною поштою.
# два) Інший поширений приклад виклику методу void - це оновлені запити до БД, які беруть певний вхід і нічого не повертають.
Методи запобігання порожнечі (тобто методи, які нічого не повертають або викликають виняток), можна обробляти за допомогою doNothing (), doThrow () і doAnswer (), doCallRealMethod () функції . Для цього потрібно встановити заглушку, використовуючи вищезазначені методи відповідно до очікуваних тестів.
Крім того, зауважте, що всі виклики методу void за замовчуванням висміюються з doNothing (). Отже, навіть якщо явне налаштування фіксованого режиму не виконано НІСЧАЙНИЙ викликів методу, поведінка за замовчуванням як і раніше виконується doNothing ().
Давайте подивимося приклади для всіх цих функцій:
Для всіх прикладів припустимо, що існує клас StudentScoreUpdates який має метод calcuSumAndStore (). Цей метод обчислює суму балів (як вхідні дані) і викликає a порожнеча метод updateScores () на екземплярі databaseImplementation.
public class StudentScoreUpdates { public IDatabase databaseImpl; public StudentScoreUpdates(IDatabase databaseImpl) { this.databaseImpl = databaseImpl; } public void calculateSumAndStore(String studentId, int() scores) { int total = 0; for(int score : scores) { total = total + score; } // write total to DB databaseImpl.updateScores(studentId, total); } }
Ми будемо писати модульні тести для виклику методу mock з наведеними нижче прикладами:
# 1) doNothing () - doNothing () - це поведінка за замовчуванням для викликів методу void у Mockito, тобто навіть якщо ви підтвердите виклик методу void (без явного налаштування void для doNothing (), перевірка все одно буде успішною)
найкраще програмне забезпечення для складання блок-схем
public void calculateSumAndStore_withValidInput_shouldCalculateAndUpdateResultInDb() { // Arrange studentScores = new StudentScoreUpdates(mockDatabase); int() scores = {60,70,90}; Mockito.doNothing().when(mockDatabase).updateScores(anyString(), anyInt()); // Act studentScores.calculateSumAndStore('student1', scores); // Assert Mockito.verify(mockDatabase, Mockito.times(1)).updateScores(anyString(), anyInt()); }
Інші звичаї поряд із doNothing ()
до) Коли метод void викликається кілька разів, і ви хочете встановити різні відповіді для різних викликів, наприклад - doNothing () для першого виклику та викинути виняток для наступного виклику.
Наприклад :Налаштуйте макет так:
Mockito. doNothing ().doThrow(new RuntimeException()).when(mockDatabase).updateScores( anyString (), anyInt ());
б) Коли потрібно захопити аргументи, з якими був викликаний метод void, слід використовувати функціональність ArgumentCaptor у Mockito. Це дає додаткову перевірку аргументів, з якими був викликаний метод.
Приклад з ArgumentCaptor:
public void calculateSumAndStore_withValidInput_shouldCalculateAndUpdateResultInDb() { // Arrange studentScores = new StudentScoreUpdates(mockDatabase); int() scores = {60,70,90}; Mockito.doNothing().when(mockDatabase).updateScores(anyString(), anyInt()); ArgumentCaptor studentIdArgument = ArgumentCaptor.forClass(String.class); // Act studentScores.calculateSumAndStore('Student1', scores); // Assert Mockito.verify(mockDatabase, Mockito.times(1)).updateScores(studentIdArgument.capture(), anyInt()); assertEquals('Student1', studentIdArgument.getValue()); }
# 2) doThrow ()- Це корисно, коли ви просто хочете створити виняток, коли метод void викликається із методу, що тестується.
Наприклад:
Mockito.doThrow(newRuntimeException()).when(mockDatabase).updateScores ( anyString (), anyInt ());
# 3) doAnswer ()- doAnswer () просто надає інтерфейс для виконання власної логіки.
Наприклад Модифікація деякого значення за допомогою переданих аргументів, повернення користувацьких значень / даних, які звичайна заглушка не могла повернути, особливо для методів void.
З метою демонстрації - я заглушив метод void updateScores (), щоб повернути ' відповісти () ”Та надрукуйте значення одного з аргументів, який повинен був бути переданий, коли слід було викликати метод.
Приклад коду:
@Test public void calculateSumAndStore_withValidInput_shouldCalculateAndUpdateResultInDb() { // Arrange studentScores = new StudentScoreUpdates(mockDatabaseImpl); int() scores = {60,70,90}; Mockito.doCallRealMethod().when(mockDatabaseImpl).updateScores(anyString(), anyInt()); doAnswer(invocation -> { Object() args = invocation.getArguments(); Object mock = invocation.getMock(); System.out.println(args(0)); return mock; }).when(mockDatabaseImpl).updateScores(anyString(), anyInt()); // Act studentScores.calculateSumAndStore('Student1', scores); // Assert Mockito.verify(mockDatabaseImpl, Mockito.times(1)).updateScores(anyString(), anyInt()); }
# 4) doCallRealMethod ()- Часткові знущання схожі на заглушки (де ви можете викликати реальні методи для деяких методів, а заглушити інші).
Для методів void mockito надає спеціальну функцію, яка називається doCallRealMethod (), яку можна використовувати під час спроби встановити макет. Що це буде робити, це викликати метод real void із фактичними аргументами.
Наприклад:
Mockito. doCallRealMethod ().when(mockDatabaseImpl).updateScores( anyString (), anyInt ());
Поради та підказки
# 1) Включення декількох статичних класів в один і той же метод / клас тесту- Використання PowerMockito якщо є необхідність знущатися над кількома статичними фінальними класами, тоді імена класів у @ Підготовка до тесту анотація може згадуватися як значення, розділене комами, як масив (він по суті приймає масив імен класів).
Приклад:
@PrepareForTest({PriceCalculator.class, DiscountCategoryFinder.class})
Як показано у прикладі вище, припустимо, що і PriceCalculator, і DiscountCategoryFinder є завершальними класами, над якими потрібно знущатися. Обидва вони можуть бути згадані як масив класів в анотації PrepareForTest і можуть бути застосовані в методі тестування.
# 2) Позиціонування атрибута PrepareForTest - Позиціонування цього атрибута має важливе значення щодо виду тестів, які входять до класу Тест.
Якщо у всіх тестах потрібно використовувати один і той самий підсумковий клас, то має сенс згадати цей атрибут на рівні тестового класу, що просто означає, що підготовлений клас буде доступний для всіх Методів тестування. На противагу цьому, якщо анотація згадується у методі тестування, вона буде доступна лише для конкретних тестів
Висновок
У цьому підручнику ми обговорили різні підходи до знущання над статичними, остаточними та недійсними методами.
Хоча використання великої кількості статичних або остаточних методів заважає тестуванню, і все ж існує підтримка для тестування / знущань, яка допомагає у створенні модульних тестів, щоб досягти більшої впевненості в коді / застосуванні навіть для застарілого коду, який зазвичай не використовується для бути розробленим для перевірки.
Що стосується статичних і остаточних методів, Mockito не має готової підтримки, але такі бібліотеки, як PowerMockito (які багато чого успадковують від Mockito), надають таку підтримку і повинні фактично виконувати маніпуляції з байт-кодами, щоб підтримувати ці функції.
Mockito з коробки підтримує заглушення методів порожнеч і пропонує різні методи, такі як doNothing, doAnswer, doThrow, doCallRealMethod тощо, і може використовуватися відповідно до вимог тесту.
Найпоширеніші запитання щодо інтерв’ю Mockito містять короткий опис у нашому наступному уроці.
НАЗАД Підручник | НАСТУПНИЙ підручник
Рекомендована література
- Підручник Mockito: Mockito Framework для знущань під час модульного тестування
- Найпопулярніші 12 запитань інтерв’ю Mockito (глузуюче рамкове інтерв’ю)
- Статична в C ++
- Потоки Java з методами та життєвим циклом
- Створення знущань та шпигунів у Mockito за допомогою прикладів коду
- Різні типи збігів, надані Mockito
- Методи та методи запобігання дефектам
- Як використовувати методи у SoapUI для масового виконання тесту - Підручник з SoapUI №10