Иногда я использую FizzBuzz, чтобы продемонстрировать новичкам основы модульного тестирования. Хотя FizzBuzz действительно простая задача, ее также можно использовать для демонстрации более продвинутых методов модульного тестирования, таких как макет .
FizzBuzz Kata:
« Напишите программу, которая печатает числа от 1 до 100. Но для кратных трех выведите« Fizz »вместо числа, а для кратных пяти выведите« Buzz ». Для чисел, кратных трем и пяти, выведите «FizzBuzz» «.
Возможное решение алгоритма FizzBuzz:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public class FizzBuzz { private static final int FIVE = 5; private static final int THREE = 3; public String calculate(int number) { if (isDivisibleBy(number, THREE) && isDivisibleBy(number, FIVE)) { return "FizzBuzz"; } if (isDivisibleBy(number, THREE)) { return "Fizz"; } if (isDivisibleBy(number, FIVE)) { return "Buzz"; } return "" + number; } private boolean isDivisibleBy(int dividend, int divisor) { return dividend % divisor == 0; }} |
Поскольку приведенный выше код решает алгоритм FizzBuzz, он не решает проблему FizzBuzz. Чтобы закончить, нам нужен код для печати чисел от 1 до 100 с использованием алгоритма. И эта часть кода может быть использована для демонстрации идеи насмешек в JUnit с Mockito.
В результате этого упражнения я получил NumberPrinter который принимает два аргумента: Printer и NumberCalculator и имеет один открытый метод для печати чисел:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
public class NumberPrinter { private NumberCalculator numberCalculator; private Printer printer; public NumberPrinter(NumberCalculator numberCalculator, Printer printer) { this.numberCalculator = numberCalculator; this.printer = printer; } public void printNumbers(int limit) { if (limit < 1) { throw new RuntimeException("limit must be >= 1"); } for (int i = 1; i <= limit; i++) { try { printer.print(numberCalculator.calculate(i)); } catch (Exception e) { // noop } } }}public interface NumberCalculator { String calculate(int number);}public interface Printer { void print(String s);} |
С введенными интерфейсами у меня есть не только тестируемый, но и более надежный код. Чтобы протестировать NumberPrinter я просто высмеиваю зависимости с мощью и простотой Mockito. С аннотациями Mockito код теста конфигурации читается лучше.
Особенности Mockito продемонстрировали:
- создание и введение макетов
- методы-заглушки также с настройкой различного поведения для последовательных вызовов методов.
- заглушение пустого метода с исключением
- верификация
Использованные аннотации:
-
@RunWith(MockitoJUnitRunner.class)— инициализирует@Mockперед каждым методом тестирования -
@Mock— помечает поле как фиктивное -
@InjectMocks— помечает поле, в которое должно быть выполнено внедрение
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
@RunWith(MockitoJUnitRunner.class)public class NumberPrinterTest { @Mock private Printer printer; @Mock private NumberCalculator numberCalculator; @InjectMocks private NumberPrinter numberPrinter; @Test public void printsCalculatorResultsHundredTimes() { // arrange int limit = 100; when(numberCalculator.calculate(anyInt())) .thenReturn("0") // first invocation returns "0" .thenReturn("1"); // other invocations return "1" // act numberPrinter.printNumbers(limit); // assert verify(numberCalculator, times(limit)).calculate(anyInt()); verify(printer, times(1)).print("0"); verify(printer, times(limit - 1)).print("1"); verifyNoMoreInteractions(numberCalculator, printer); } @Test public void continuesOnCalculatorOrPrinterError() { // arrange when(numberCalculator.calculate(anyInt())) .thenReturn("1") .thenThrow(new RuntimeException()) .thenReturn("3"); // stub the void method with an exception doThrow(new RuntimeException()).when(printer).print("3"); // act numberPrinter.printNumbers(3); // assert verify(numberCalculator, times(3)).calculate(anyInt()); verify(printer).print("1"); verify(printer).print("3"); verifyNoMoreInteractions(numberCalculator, printer); }} |
Наслаждайтесь Мокито !
- Хотите узнать больше об аннотациях Mockito? Взгляните на «Mockito — @Mock, @Spy, @Captor и @InjectMocks» Евгения Парашива: http://www.baeldung.com/mockito-annotations
- Ищете примеры кода? Взгляните на демонстрационный проект юнит-тестирования, представляющий различные аспекты юнит-тестирования, включая макетирование: https://github.com/kolorobot/unit-testing-demo
| Ссылка: | Модульное тестирование с FizzBuzz и Mockito от нашего партнера JCG Рафаля Боровца в блоге Codeleak.pl . |