我目前正在为战略设计模式编写单元测试。我正在将系统输出与assertEquals方法中的字符串进行比较。输出看起来相同但我的测试仍然失败...我在想我忘了与新线或标签有关的事情了?
我的单元测试:
import static org.junit.Assert.*;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class MiniDuck1Test {
private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();
@Before
public void setUpStreams() {
System.setOut(new PrintStream(outContent));
System.setErr(new PrintStream(errContent));
}
@After
public void cleanUpStreams() {
System.setOut(null);
System.setErr(null);
}
@Test
public void testDuck1() {
Duck mallard = new MallardDuck();
mallard.performQuack();
mallard.performFly();
Duck model = new ModelDuck();
model.performFly();
model.setFlyBehavior(new FlyRocketPowered());
model.performFly();
assertEquals("Quack\nI'm flying!!\nI can't fly\nI'm flying with a rocket", outContent.toString().trim());
}
}
输出(第二行和第三行显示为红色):
Quack
I'm flying!!
I can't fly
I'm flying with a rocket
修改
最快的解决方案似乎是在我的“\ n”前添加“\ r \ n”。多个答案告诉我,这需要在Windows上完成。应用此之后,我的assertEquals看起来像:
assertEquals("Quack\r\nI'm flying!!\r\nI can't fly\r\nI'm flying with a rocket", outContent.toString().trim());
另外:我忘了提到大部分代码来自Eric Freeman,Elisabeth Robson,Bert Bates和Kathy Sierra的书“Head First Design Patterns”。
答案 0 :(得分:2)
如果您正在寻找与平台无关的方式,那么除了其他答案之外......
快速平台无关的解决方案可以替换行分隔符
String expected = "Quack\nI'm flying!!\nI can't fly\nI'm flying with a rocket"
.replaceAll("\\n|\\r\\n", System.getProperty("line.separator"));
assertEquals(expected, outContent.toString().trim());
或使用PrintWriter
构建预期的字符串。
StringWriter expectedStringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(expectedStringWriter);
printWriter.println("Quack");
printWriter.println("I'm flying!!");
printWriter.println("I can't fly");
printWriter.println("I'm flying with a rocket");
printWriter.close();
String expected = expectedStringWriter.toString();
assertEquals(expected, outContent.toString());
或创建一个自己的断言类来重复使用它
class MyAssert {
public static void assertLinesEqual(String expectedString, String actualString){
BufferedReader expectedLinesReader = new BufferedReader(new StringReader(expectedString));
BufferedReader actualLinesReader = new BufferedReader(new StringReader(actualString));
try {
int lineNumber = 0;
String actualLine;
while((actualLine = actualLinesReader.readLine()) != null){
String expectedLine = expectedLinesReader.readLine();
Assert.assertEquals("Line " + lineNumber, expectedLine, actualLine);
lineNumber++;
}
if(expectedLinesReader.readLine() != null){
Assert.fail("Actual string does not contain all expected lines");
}
} catch (IOException e) {
Assert.fail(e.getMessage());
} finally {
try {
expectedLinesReader.close();
} catch (IOException e) {
Assert.fail(e.getMessage());
}
try {
actualLinesReader.close();
} catch (IOException e) {
Assert.fail(e.getMessage());
}
}
}
}
如果测试失败,您可以提供更好的问题描述。 E.g。
MyAssert.assertLinesEqual(
"Quack\nI'm flying!!\nI can not fly\nI'm flying with a rocket\n",
outContent.toString());
将输出
org.junit.ComparisonFailure: Line 2
Expected :I can not fly
Actual :I can't fly
答案 1 :(得分:2)
到目前为止所有其他答案在技术上是正确的;但他们仍然没有提到一个核心问题:捕获 stdout / stderr然后进行精确的字符串匹配只是不好的做法; 假设您的班级写在那里。
当您测试多个方法调用时,甚至更多,并期望某些 final 输出“证明”所有方法都被调用,依此类推。
所以,是的,从理论上讲,你可以这样做(为了培训/学习目的);但你在这里使用的“模式”只是简单地说是“坏习惯”。当您稍后决定删除这些打印语句时会发生什么(因为,生产代码不执行打印语句)。然后你所有的测试都变得毫无价值。或者当其他一些用户将字符串中的一个字符更改为stdout时?
因此:真正的答案是退后一步,考虑这些方法调用会导致的真正“副作用”是什么;并寻找更好的方法来验证它们。
答案 2 :(得分:1)
尝试使用\ r \ n而不是\ n。
assertEquals("Quack\r\nI'm flying!!\r\nI can't fly\r\nI'm flying with a rocket", outContent.toString().trim());
答案 3 :(得分:1)
可能是,您使用的是Windows系统,需要检查\r\n
而非\n