-2

I am trying to create a test that asserts that two ArrayLists are equal. When running the test, I am getting an error that there is one difference between the expected and actual: there is a whitespace at the end of the arraylist.

The problem isn't caused by anything inside the arraylist, the problem is after the close of the arraylist. As far as I know, there is no trim function for this in java or a junit test which ignores whitespace.

ArrayList<Quote> expected = new ArrayList<>();

        Quote q1 = new Quote("Test Test", "This is a quote.");
        Quote q2 = new Quote("Author Two", "Quote 2.");
        Quote q3 = new Quote("Unknown", "This quote does not have an author.");
        Quote q4 = new Quote("Author Three-three", "Quote 3.");

        expected.add(q1); expected.add(q2); expected.add(q3); expected.add(q4);

What this gives me is: java.util.ArrayList<[This is a quote. - Test Test, Quote 2. - Author Two, This quote does not have an author. - Unknown, Quote 3. - Author Three-three]>_

(I put a underscore where the whitespace is)

What I expect is: java.util.ArrayList<[This is a quote. - Test Test, Quote 2. - Author Two, This quote does not have an author. - Unknown, Quote 3. - Author Three-three]>

This does not include a whitespace.

I don't know why I am getting the whitespace nor do I know how to get rid of it. Any help would be appreciated.

For more context, the entire tester file

public class ImportQuotesTest {

    BufferedReader reader;
    @Before
    public void setUp() throws Exception {
        File file = new File("C:\\Users\\homba\\Documents\\QuotesProject\\src\\ImportQuotesTest.txt");

        reader = new BufferedReader(new FileReader(file));
    }

    @Test
    public void fillList() throws IOException {
        ArrayList<Quote> actual = ImportQuotes.fillList(reader);
        ArrayList<Quote> expected = new ArrayList<>();

        Quote q1 = new Quote("Test Test", "This is a quote.");
        Quote q2 = new Quote("Author Two", "Quote 2.");
        Quote q3 = new Quote("Unknown", "This quote does not have an author.");
        Quote q4 = new Quote("Author Three-three", "Quote 3.");

        expected.add(q1); expected.add(q2); expected.add(q3); expected.add(q4);

        Assert.assertEquals(expected,actual);
    }
}```

  • 1
    You haven't shown the code that actually prints or compares your list. What does that look like? – Marvin Jul 18 '19 at 20:30
  • I am just comparing the two as objects using Assert.assertEquals() like so ```java Assert.assertEquals(expected,actual); ``` – Rishik Hombal Jul 18 '19 at 20:35
  • 4
    Please [edit] the question and add all relevant code there. Java does not magically add whitespace, so there must be something in your test. Try to provide a [mcve]. – Marvin Jul 18 '19 at 20:36
  • 1
    ...and what's the content of the file? Your issue might be inside `ImportQuotes.fillList(reader)`. – x80486 Jul 18 '19 at 20:39

1 Answers1

0

Ah yeah, I stumbled into that once! First of all, if you're doing a unit test, just iterate through the whole list and assert each element or build a String yourself. I think I saw this in eclipse. It's running its own version of junit somehow and I think the tests pass when running from mvn test in command line.

To answer your question short:

  1. You can use Hamcrest if you can: Assert about a List in Junit

  2. Iterate: for (int i = 0; i< list1.size; i++) { assertEquals(list1.get(i), list2.get(i)); }

  3. StringBuilder sb1 = new StringBuilder(); StringBuilder sb2 = new StringBuilder(); list1.forEach(sb1::append); list2.forEach(sb1::append); assertEquals(sb1.toString(), sb2.toString()

Prefered way is number 1 or 3.

ACV
  • 9,964
  • 5
  • 76
  • 81
  • Yeah you're right, this test passes from the command line and only fails when I'm using Intellij. Glad that I'm not doing something wrong. Thank you! – Rishik Hombal Jul 18 '19 at 20:44
  • 1
    You shouldn't accept this answer, it's a hack, nor you should compare arrays in such a way. If anything, try with `Assert.assertArrayEquals`. – x80486 Jul 18 '19 at 20:48
  • @x80486 assertArrayEquals will not work because this is a List object not an array. The original assertEquals should work. – Rishik Hombal Jul 18 '19 at 20:54
  • 1
    `assertEquals` eventually just runs the `equals` of the object (in this case the `ArrayList`). That is something fundamentally different from comparing the two `toString()`s. I'm not sure how the `equals` of your `Quote` class is implemented, but if that is comparing correctly, then I bet that your quotes are indeed different (even though they appear equal). Does your test succeed if you loop over them and compare them separately? – Ivar Jul 18 '19 at 21:01
  • When you iterate over both lists, it's better to use [the Iterator](https://stackoverflow.com/questions/15985266/how-to-iterate-through-two-arraylists-simultaneously). On an ArrayList calling `.get()` isn't too terrible, but on a LinkedList calling `.get()` like that is pretty inefficient. – Ivar Jul 18 '19 at 21:04
  • To test your suggestion, I made a little test: ```java for (int i = 1; i < expected.size(); i++){ Assert.assertTrue(expected.get(i).equals(actual.get(i))); //Assert.assertEquals(expected.get(i), actual.get(i)); } ``` The assertTrue passes but the assertEquals fails. If junit is using the equals method I made with my quote class I don't know why it fails: ```public boolean equals(Quote q) { if (quote.equals(q.getQuote()) && author.equals(q.getAuthor())) return true; return false; } ``` – Rishik Hombal Jul 18 '19 at 21:10
  • @RishikHombal You can try to use the debugger by setting a breakpoint on the `Assert.assertEquals` and step into it and see what paths it takes. If `.equals()` returns true, then `assertEquals` should do the same. I'm kind of curious now why they would differ. – Ivar Jul 18 '19 at 21:20
  • @Ivar I am not too good with the debugger so I am not sure how to find the paths – Rishik Hombal Jul 18 '19 at 21:33