这个问题在这里已有答案:
我想使用参数[-1,0,24,2,32]测试方法setDay()。
我知道Scanner读卡器可以
String test="-1 0 24 2 32";
Scanner reader=new Scanner(test);
主要问题是无限循环和无效方法。我们如何测试这种代码?这是示例代码:
public NameOfTheDay(){
int day=1;
}
{...}
public void setDay(Scanner reader) {
while (true) {
System.out.print("Day: ");
String input = reader.nextLine();
if (input.matches("\\d{2}")) {
int day = Integer.parseInt(input);
if (day > 0 && day < 32) {
this.day = day;
return;
}
}
System.out.println("Wrong day. Try again.");
}
}
谢谢你的回答。
我不会关注您的方法的内容,而只关注如何对希望Scanner对象作为参数的方法进行单元测试的问题。
答案很简单:将测试输入数据作为String提供,并在其周围构建扫描程序,如下所示:
@Test
public void testSetDay_positive() {
String testInput = "23\n";
Scanner testScanner = new Scanner(testInput);
NameOfTheDay notd = new NameOfTheDay();
notd.setDay(testScanner);
Assert.assertEquals(23, notd.getDay()); // or whatever condition to test
}
现在变得更难了。也许您想首先测试无效输入,并确保使用第二个输入?
@Test
public void testSetDay_negative_then_positive() {
String testInput = "999\n23\n"; // two lines of input here
Scanner testScanner = new Scanner(testInput);
NameOfTheDay notd = new NameOfTheDay();
notd.setDay(testScanner);
Assert.assertEquals(23, notd.getDay()); // or whatever condition to test
}
如果要测试是否将错误消息写入System.out
,则必须将其替换为自定义流以进行后续测试:
ByteArrayOutputStream mockOut = new ByteArrayOutputStream();
PrintStream newOut = new PrintStream(mockOut);
System.setOut(newOut);
// execute test from above
Assert.assertTrue(new String(mockOut.toByteArray(), "UTF-8").contains("Wrong day. Try again."));
尽管如此,对您的问题的大多数评论都包含有价值的输入(移动验证到额外的方法等)应该考虑。
我们如何测试这种代码?
你不能。
unittest验证您的代码在测试中的公共可观察行为,其中“公共可观察行为”是任何rreturn值或与依赖项的通信。
使用测试双精度检查与依赖项的通信,我们(通常)使用模拟框架创建测试双精度并将其注入到测试中的代码中。
一个主要的先决条件是您的代码干净地包含单一责任/分离关注模式。
您的代码不会返回任何内容,也不可能替换感兴趣的依赖项(此处为System.out
),因为它将业务逻辑与用户交互混合在一起。
有些人可能会争辩说,你可以为System.out
分配测试双或使用
PowerMock
替换依赖项,但恕我直言,这只是你的糟糕设计投降,并不会随着你的程序增长而得到回报。