AssertJ `containsExactly` assertion on list with wildcard

给你一囗甜甜゛ 提交于 2020-05-15 10:17:05

问题


I have a getter returning a List with a wildcard:

import java.util.List;

public interface Foo {
    List<? extends Bar> getList();
}

Where Bar is an other interface.

When I write an assertion with AssertJ like this:

assertThat(foo.getList()).containsExactly(bar1, bar3);

EDIT: my complete usage is to chain a usingElementComparator and to provide a Comparator<Bar> to compare the expected Bar instances.

Comparator<Bar> comparator = createBarComparator()
assertThat(foo.getList()).usingElementComparator(comparator).containsExactly(bar1, bar3);

I get this compilation error:

The method containsExactly(capture#46-of ? extends Bar...) in the type ListAssert is not applicable for the arguments (Bar, Bar)


My first solution is to cast the result:

assertThat((List<Bar>)foo.getList()).containsExactly(bar1, bar3);

Then I get a warning:

Type safety: Unchecked cast from List to List

Warning can be removed with @SuppressWarnings("unchecked"), but still the cast in the middle do not make the assertion really readable.


My second solution is to indicate the value the ELEMENT generic parameter:

Assertions.<Bar>assertThat(foo.getList()).containsExactly(bar1, bar3);

A little better, but also not that nice (no static import possible, the beginning of the line do not facilitate the readability)


I guess I am looking for an other assertThat method for list, where the class type can be specified as second parameter:

@CheckReturnValue
public static <ELEMENT> ListAssert<ELEMENT> assertThat(List<? extends ELEMENT> actual, Class<ELEMENT> c) {
    return AssertionsForInterfaceTypes.assertThat(actual);
}

This way I should be able to write something like this:

Assertions.assertThat(foo.getList(), Bar.class).containsExactly(bar1, bar3);

回答1:


That used to work with the Oracle JDK 7 compiler but this was actually a bug in the compiler, this has been fixed in Java 8 JDK so having the compilation error is the normal behavior (can't find the bug reference though).

I would be happy to support but I'm not sure this is possible in AssertJ except by removing all generics usage in collections assertions.

assertThat(List, Class) already exists but for another purpose so no luck for that option.

A possible hack is to define your own assertThat method like that:

public static <T> ListAssert<Object> assertThat(final List<T> list) {
    return Assertions.assertThat(list);
}

The trick being to return a ListAssert<Object>.

Although I understand the rationale of the compilation error I disagree with it for read only method.



来源:https://stackoverflow.com/questions/47317425/assertj-containsexactly-assertion-on-list-with-wildcard

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!