我一直在盯着这段代码已经很长一段时间了,我真的无法弄清楚如何以及为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
的实用程序类,它是一个数组列表。
答案 0 :(得分:0)
嗯......想想这种方法的合同:它有什么承诺?它承诺打印一个整数列表,用逗号分隔,并在括号内。因此,您可以在单元测试中指定它。
编辑2:以防万一你喜欢单元测试是否按顺序打印列表:我不认为这是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);
}
请注意,您可能需要提取设置和拆卸部件,以便在其他测试中使用它并使您的测试可读。如果我没有弄错的话,JUnit提供了添加在每次测试执行之前和之后调用的代码的功能,如果您使用@Before
和@After
注释指定它。
显然,你不一定需要Mockito才能实现这一目标。您还可以编写一个实现PrintStream
的类并存储打印的字符串。在这种情况下,Mockito只允许您忽略您不关心的所有方法(即,您不需要实现整个PrintStream
接口)
关于重复存根的一个小旁注:我们需要存根两个方法print
和println
,因为两者都被使用了。此外,由于覆盖,print(String x)
与print(Object x)
不同,因此我们需要将它们都存在。
答案 1 :(得分:0)
@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]"));
}
答案 2 :(得分:0)
库System Rules有一个名为StandardOutputStreamLog的JUnit规则。使用此规则,您可以测试代码,写入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());
}
}