Incomprehensible JUnit error - java

Trying to test equality of two Maps (including order) by turning them into lists beforehand. There are probably better ways to do it, but I'd like to know why this error comes up. Here is the test:
#Test
public void sortedEntriesTest() {
List<Map.Entry<String, AtomicInteger>> actualList = stream.sortedEntries(stream.getMap());
List<Map.Entry<String, AtomicInteger>> expectedList =
expectedMap.entrySet()
.stream()
.sorted(Comparator.comparingInt(e -> -e.getValue().get()))
.collect(Collectors.toList());
Assert.assertThat(expectedList, is(actualList));
}
Here is the error:
java.lang.AssertionError:
Expected: is <[file=1, for=1, project=1, is=1, an=1, just=1, example=1, this=2]>
but: was <[file=1, for=1, project=1, is=1, an=1, just=1, example=1, this=2]>
Expected :is <[file=1, for=1, project=1, is=1, an=1, just=1, example=1, this=2]>
Actual :<[file=1, for=1, project=1, is=1, an=1, just=1, example=1, this=2]>

Try
Assert.assertThat(expectedList, is(equalTo(actualList)));
instead.

Explanation:
You are comparing references of two different objects, which are (just as the objects) different. That is why You are getting the AssertionError - first reference is not the second reference.
Solution:
Use the equals method (link to the Java documentation for List.equals()), and it will compare the contents of the lists, also by calling the Map's equals method.
Assert.assertTrue(expectedList.equals(actualList));
Documentation on Assert.assertTrue
Also, check this StackOverflow question and the first (selected) answer - comparing two maps.
Edit
Since You told that the error is still here, then it might be a problem in the list's items. You should check how Map.Entry instances in the expectedList and actualList are being created. Their actual types might be different, since the Map.Entry is just an interface.
Also, I suggest You to use a simpler method of getting the desired values for comparison.

Related

JUnit - compare unknown Collection and ArrayList

I want to compare Collection (products) (in my case it is LinkedHashMap$LinkedValues) and ArrayList.
The test
assertThat(products, equalTo(Lists.newArrayList(product1, product2, product3)));
doesn't work because LinkedValues doesn't implement equals method.
So I changed my test to:
assertThat(new ArrayList<>(products), equalTo(Lists.newArrayList(product1, product2, product3)));
Is there a better solution where I do not have to check if the collection implements equals method?
Since you're using Hamcrest, you should use the slightly confusingly named method Matchers.contains(). It checks whether the target collection contains the same elements in the same order as the original collection.
Given
Map<String, String> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("a", "A");
linkedHashMap.put("b", "B");
This will pass:
assertThat(linkedHashMap.values(), contains("A", "B"));
and this would fail:
assertThat(linkedHashMap.values(), contains("B", "A"));
Note that Hamcrest has been long dead and even though it works fine and is okay for 99% of usages, you will be shocked by how good AssertJ is, how much functionality it provides and how easy asserting can be.
With AssertJ:
assertThat(linkedHashMap.values()).containsExactly("A", "B");
Assuming the data type you're using already has an equals method, then there's no need to check for an (un-)implemented equals() function. Otherwise, you would have to create something that compares the data you're using.
On a side note, the two lines of code you have are identical. Did you mean to put something else in the second line?
You can use Arrays.equals:
assertTrue(Arrays.equals(products.toArray(), new Product[] {product1, product2, product3}));
This checks array sizes and odering of items. Your product class should implement equals() to be something meaningful.
Note that you can use ArrayList.toArray() to get an array if needed.

How to assert that two Lists<String> are equal, ignoring order

I am using AssertJ and I am trying to assert that two List<String> contain same strings, ignoring the order.
List<String> expected = Arrays.asList("Something-6144-77.pdf", "d-6144-77.pdf", "something-6144-78.pdf", "Something-6144-8068.pdf");
List<String> actual = new ArrayList<String>();
assertThat(actual.size()).isEqualTo(expected.size());
// This line gives the error: "The method containsExactlyInAnyOrder(String...) in the type ListAssert<String> is not applicable for the arguments (List<String>)"
assertThat(actual).containsExactlyInAnyOrder(expected);
How can I fix the compilation error below that is appearing when trying to use containsExactlyInAnyOrder()?
"The method containsExactlyInAnyOrder(String...) in the type ListAssert is not applicable for the arguments (List)"
Both the answers (by jlordo and by dasblinkenlight) work, but are workarounds rather than the correct way to do it.
There is a method in the AssertJ library for specifically checking if a List contains all values, regardless of order, in another Iterable. It is called containsOnlyElementsOf():
public SELF containsOnlyElementsOf(Iterable<? extends ELEMENT> iterable)
Same semantic as ObjectEnumerableAssert.containsOnly(Object[]) : verifies that actual contains all the elements of the given iterable and nothing else, in any order.
Example :
Iterable<Ring> rings = newArrayList(nenya, vilya);
// assertion will pass
assertThat(rings).containsOnlyElementsOf(newLinkedList(nenya, vilya))
.containsOnlyElementsOf(newLinkedList(nenya, nenya, vilya, vilya));
// assertion will fail as actual does not contain narya
assertThat(rings).containsOnlyElementsOf(newLinkedList(nenya, vilya, narya));
// assertion will fail as actual contains nenya
assertThat(rings).containsOnlyElementsOf(newLinkedList(vilya));
So, this method is the one you should use, like below. There is no need to cast or transform your List to an Array.
assertThat(actual).containsOnlyElementsOf(expected);
As a side note, your assertion on the size of the list is redundant:
assertThat(actual.size()).isEqualTo(expected.size());
This is already covered in the assertion that the lists contain the same elements.
Finally, if you do need to assert that a list has a specific site, AssertJ has a built-in method for this (hasSameSizeAs()):
assertThat(actual).hasSameSizeAs(expected);
The error message gives you the solution:
The method containsExactlyInAnyOrder(String...)
String... is a any number of strings but can be passed as an array as well:
assertThat(actual).containsExactlyInAnyOrder((String[]) expected.toArray(new String[expected.size()]));
The cast is necessary here and that code is given under the assumption that the expected element is created different than in your example, as it doesn't make sense to convert an array to a list and back.
Here some documentation to varargs (Arbitrary number of arguments, the ...): https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html
In newer versions of assertj there is a containsExactlyInAnyOrderElementsOf for exactly this purpose.
Your example boils down to
assertThat(actual).containsExactlyInAnyOrderElementsOf(expected);
Since the method takes String..., you should pass an array instead of a list:
String[] expected = new String[] {
"Something-6144-77.pdf"
, "d-6144-77.pdf"
, "something-6144-78.pdf"
, "Something-6144-8068.pdf"
};
or call it with the list of items inlined:
assertThat(actual).containsExactlyInAnyOrder(
"Something-6144-77.pdf"
, "d-6144-77.pdf"
, "something-6144-78.pdf"
, "Something-6144-8068.pdf"
);

Comparing two list of objects in JUnit [duplicate]

This question already has answers here:
AssertEquals 2 Lists ignore order
(10 answers)
Java Compare Two Lists
(11 answers)
Closed 6 years ago.
I am writing JUnit Test case for my java project and using Coverage Tool to check the lines of code are covered. The problem is: I've two list of objects. I need to compare the results of object to be equal using assertTrue or any other possible assert statements. I am getting error like Assertion Error by using below assert statements. Is there any solution to compare two lists easily?
//actual
List<ProjectData> actuals = ProjectManagerDao.getProjects("x", "y", "z");
// expected
List<ProjectData> expecteds = new ArrayList<>();
ProjectData p1 = new ProjectData();
p1.setId("a");
p1.setName("b");
expecteds.add(p1);
assertTrue(JsonProvider.getGson().toJson(actuals).equalsIgnoreCase(JsonProvider.getGson().toJson(expecteds)));
//or
assertTrue(actuals.equalIgnoreCase(expeteds);//Not working for list of objects but working for comparing two strings
This differs from Java Compare Two Lists in that I need to be able to assert equality in jUnit, not just compare the lists.
Use Assert.assertArrayEquals(Object[] expecteds, Object[] actuals) method to compare two array for content equality:
Assert.assertArrayEquals(expected.toArray(), actuals.toArray());
equals method compares arrays for being the same reference so it's not suitable in test cases.
For your other question: Remember to use org.junit.Assert not junit.Assert which became obsolete.
In short: there is exactly one assert that one needs when writing JUnit tests: assertThat
You just write code like
assertThat("optional message printed on fails", actualArrayListWhatever, is(expectedArrayListWhatever))
where is() is a hamcrest matcher.
This approach does work for all kinds of collections and stuff; and it does the natural "compare element by element" thing (and there are plenty of other hamcrest matcher that one can use for more specific testing; and it is also pretty easy to write your own matchers).
( seriously; I have not seen a single case where assertThat() would not work; or would result in less readable code )
You can use
Assert.assertEquals(java.lang.Object expected, java.lang.Object actual);
example:
ArrayList<String> list1 = new ArrayList<>();
list1.add("hello");
ArrayList<String> list2 = new ArrayList<>();
list2.add("hello");
Assert.assertEquals(list1, list2);
source: Junit API
or if you want to use the arrays comparison method you can as below
ArrayList<String> list1;
ArrayList<String> list2;
Assert.assertArrayEquals(list1.toArray(), list2.toArray());
I would recommend you to use the assertEquals method.
PS: (the user defined objects stored inside the list should have the equals and hashcode methods overridden)

Unsupported Operation on AbstractList.add()

I got a method
foo(list);
that get's a
List<SomeEntit>
as input.
My method foo looks somewhat like the following:
public void foo(List<SomeEntity someEntities) {
someEntities.add(anotherEntity);
}
I then get an "javax.ejb.EJBException: java.lang.UnsupportedOperationException" caused by "java.lang.UnsupportedOperationException: null" at "at java.util.AbstractList.add(AbstractList.java:148)"
Can you tell me why this is happening? I hope that my code example is not too minimal.
Some lists are unmodifiable. The operation of adding elements is then "unsupported".
Java collections framework does not have a distinct type for unmodifiable lists or other unmodifiable collections. You never really know if it is allowed to add something.
All you can do is to specify that the list that is passed must be modifiable.
It seems that the actual type of the List you get as the input does not override the add method.
Try converting that list to a list implementation that does, like ArrayList:
List<SomeEntity> newList = new ArrayList<>(list);
foo(newList);

comparing two XmlBeans Objects for equality

I've an XML Beans Interface called SynonymsRequest with:
public interface SynonymsRequest extends org.apache.xmlbeans.XmlObject {...}
I want to test two instances of SynonymsRequest for equality:
SynonymsRequest s1 = SynonymsRequest.Factory.newInstance();
s1.setQueryText("blub");
s1.setRequesterId(BigInteger.valueOf(1));
SynonymsRequest s2 = SynonymsRequest.Factory.newInstance();
s2.setQueryText("guck");
s2.setRequesterId(BigInteger.valueOf(1));
I've tried the following:
assertTrue(s1.equals(s2)); => assertion does not pass
assertEquals(0, s1.compareTo(s2)); => throws ClassCastException
assertEquals(0, s1.compareValue(s2)); => assertion does not pass (returns 2, not compareable)
assertTrue(s1.valueEquals(s2)); => always returns true, no matter if the two instances are equal
So what is the proper way of doing this?
If it doesn't impact the performance of your program, you could compare them like this:
assertTrue(s1.xmlText().equals(s2.xmlText()));
Otherwise, I guess you will have to write your own custom comparator.
As I understand, the comparison compares two simple values only. It cannot deduct your desired comparison algorithm.
Or I don't understand what exactly do you mean?
XmlBeans doesn't support a deep comparison so you'll have to write your own. There was a thread on the dev mailing list a while ago about a schema-aware comparison, but I'm not sure anything became of it:
http://www.mail-archive.com/dev#xmlbeans.apache.org/msg01960.html
Noticed this a while back - if the two objects have toString() methods generated when they were made, then you can to an .equals on the toString() methods of the objects. These can be compared with relativ ease, since they will check if the output xml is equivalent.

Categories

Resources