Java: test System output, including newlines with assertEquals

I am currently writing Unit Test for a strategy design template. I am comparing System output with a string in the assertEquals method. The result looks the same, but my test continues to fail. I think I forget to do something with new lines or tabs?

My Unit Test:

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()); } } 

Output (second and third lines are displayed in red):

 Quack I'm flying!! I can't fly I'm flying with a rocket 

Edit:

The quickest solution seemed to add "\ r" before my "\ n". Several answers told me that this needs to be done for Windows. After applying this, my assertEquals looked like this:

 assertEquals("Quack\r\nI'm flying!!\r\nI can't fly\r\nI'm flying with a rocket", outContent.toString().trim()); 

Also: I forgot to mention that most of the code is from the book: "Primary Design Templates" by Eric Freeman, Elizabeth Robson, Burt Bates and Katie Sierra.

+5
source share
4 answers

In addition to other answers, if you are looking for a platform-independent way ...

A quick platform-independent solution might be to replace line separators

 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()); 

or using PrintWriter to build the expected string.

 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()); 

or create your own assert class to reuse it

 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()); } } } } 

Then you can give a better description of the problem if the test fails. For instance.

 MyAssert.assertLinesEqual( "Quack\nI'm flying!!\nI can not fly\nI'm flying with a rocket\n", outContent.toString()); 

displays

 org.junit.ComparisonFailure: Line 2 Expected :I can not fly Actual :I can't fly 
+2
source

For now, the other answers are technically correct; but still they don’t mention one basic thing: it’s just bad practice to grab stdout / stderr and then do exact string matching; , assuming your class is writing there.

Even more, when you test calls to multiple methods and expect some kind of final output to “prove” that all methods have been called, etc.

So yes, theoretically you can do this (for teaching / learning); but the "template" you use here just says "bad practice." What happens when you later decide to delete these print instructions (because, well, the production code does not make printed statements). Then all your tests will be useless. Or when some other user changes one character in the lines going to stdout?

Thus: the real answer is to step back and consider what the real “side effects” that these method calls will cause; and look for the best ways to test them.

+2
source

Try using \ r \ n instead of \ n.

 assertEquals("Quack\r\nI'm flying!!\r\nI can't fly\r\nI'm flying with a rocket", outContent.toString().trim()); 
+1
source

Maybe you are on a Windows system and should check \r\n instead of \n

+1
source

Source: https://habr.com/ru/post/1262868/


All Articles