Я довольно долго смотрел на этот код, и я действительно не могу понять, как и что делать для его тестирования JUnit.
static void printList(OrderedIntList list) {
System.out.print("[");
for (int i = 0; i < list.orderedIntegerList.length; i++) {
System.out.print(list.orderedIntegerList[i]);
if (i != list.orderedIntegerList.length - 1) {
System.out.print(", ");
}
}
System.out.println("]");
}
Этот код относится к классу утилиты, называемому orderedIntList
, который представляет собой список массивов.
Ну... подумайте о контрактах этого метода: что это обещает? Он обещает напечатать список целых чисел, разделенных запятой и внутри скобок. Таким образом, вы можете указать это в модульном тесте.
Edit2: На всякий случай, если вам понравится модульное тестирование, будет ли список напечатан в порядке: я бы не считал это свойством метода printList
. Это свойство должно быть проверено в методах, которые изменяют OrderedIntList
.
Напиши приборы для некоторых списков со строкой, которую вы ожидаете напечатать. Не забудьте углу: пустой список. Тогда, может быть, список размером 1 и один размером 10.
Чтобы проверить, что было напечатано, вы можете создать новый PrintStream
и установить значение System.out
, вызывая System.setOut
. Сделайте это в начале каждого теста и не забудьте перезагрузить System.out
(так что не забудьте сохранить его исходное значение). PrintStream
вы используете, не нуждается в фантазии: вы просто должны иметь возможность сравнивать печатный поток. Возможно, вы захотите рассмотреть возможность использования Mockito.
Редактировать:
Например, следующий код проверяет, действительно ли список, содержащий единственный элемент 4
, на самом деле печатает строку "[4]\n"
:
@Test
public void aListOfSizeOneShouldPrintTheElementWithinBrackets() {
/* Setup */
final StringBuffer printStream = new StringBuffer();
PrintStream mockedOut = mock(PrintStream.class);
Mockito.doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
printStream.append(invocation.getArguments()[0].toString());
return null;
}
}).when(mockedOut).print(any());
Mockito.doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
printStream.append(invocation.getArguments()[0].toString());
return null;
}
}).when(mockedOut).print(anyString());
Mockito.doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
printStream.append(invocation.getArguments()[0].toString()).append("\n");
return null;
}
}).when(mockedOut).println(any());
Mockito.doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
printStream.append(invocation.getArguments()[0].toString()).append("\n");
return null;
}
}).when(mockedOut).println(anyString());
PrintStream originalOut = System.out;
System.setOut(mockedOut);
/* the actual test */
ArrayList<Integer> listWithOneElement = new ArrayList<Integer>();
listWithOneElement.add(4);
OrderedIntList list = new OrderedIntList(listWithOneElement);
OrderedIntList.printList(list);
MatcherAssert.assertThat(printStream.toString(), is("[4]\n"));
/* Teardown - reset System.out */
System.setOut(originalOut);
}
Обратите внимание, что вы, вероятно, захотите извлечь setup- и часть разрыва, чтобы использовать ее в других тестах и сделать ваш тест доступным для чтения. Если я не ошибаюсь, JUnit предоставляет функциональность для добавления кода, который вызывается до и после каждого выполнения теста, если вы укажете его с помощью @Before
и @After
аннотации.
Очевидно, вам не обязательно нужно Mockito для достижения этого. Вы также можете написать класс, который реализует PrintStream
и сохраняет печатные строки. В этом случае Mockito просто позволяет игнорировать все методы, которые вам не нужны (т. PrintStream
Вам не нужно реализовывать весь интерфейс PrintStream
)
Небольшой пояс по дублированию заглушки: нам нужно заглушить оба метода, print
и println
, потому что оба используются. Кроме того, из-за переопределения print(String x)
не совпадает с print(Object x)
, поэтому нам нужно их заглушить.
В системных правилах библиотеки есть правило JUnit, называемое StandardOutputStreamLog. С помощью этого правила вы можете протестировать свой код, который записывается в System.out
:
public void MyTest {
@Rule
public final StandardOutputStreamLog log = new StandardOutputStreamLog();
@Test
public void test() {
OrderedIntList list = ...
printList(list);
assertEquals("[1,2,3,4]", log.getLog());
}
}
Ответ @Kulu Limpa правильный, но гораздо более сложный, чем реальная реализация, потому что вам нужно какое-то насмешку.
если вы реорганизуете свой код на
static void printList(OrderedIntList list) {
System.out.println(toString(list));
}
static String toString(OrderedIntList list) {
StringBuilder result = new StringBuilder();
System.out.println(toString(list));
result.append("[");
for (int i = 0; i < list.orderedIntegerList.length; i++) {
result.append(list.orderedIntegerList[i]);
if (i != list.orderedIntegerList.length - 1) {
result.append(", ");
}
}
result.append("]");
return result.toString();
}
тестирование должно быть намного проще:
@Test
public void aListOfSizeOneShouldPrintTheElementWithinBrackets() {
ArrayList<Integer> listWithOneElement = new ArrayList<Integer>();
listWithOneElement.add(4);
OrderedIntList list = new OrderedIntList(listWithOneElement);
String result = OrderedIntList.toString(list);
MatcherAssert.assertThat(result, is("[4]"));
}