简体   繁体   English

如何使JUnit assertThat()与较低的有界通配符一起工作?

[英]How to make JUnit assertThat() work with lower bounded wildcard?

initially, I had this piece of production code: 最初,我有这段生产代码:

interface ActionSequence {
   public List<Actions> getActions();

I tested classes implementing that interface with something like this: 我测试了实现该接口的类,如下所示:

assertThat(sequenceUnderTest.getActions(), is(Arrays.asList(action1, action2));

Then I figured that it might be beneficial to change the production interface to: 然后我认为将生产界面更改为:

public List<? extends Action> getActions() {

(to allow me to return lists of subclasses of Action). (允许我返回Action的子类列表)。

But now eclipse tells me: 但是现在eclipse告诉我:

The method assertThat(T, Matcher<? super T>) in the type Assert is not applicable for the arguments (List<capture#1-of ? extends Action>, Matcher<List<Action>>)

I figured: when I change the class that implements ActionInterface to do 我想:当我改变实现ActionInterface的

@Override
public List<SomeSubClassOfAction> getActions()

(instead of keeping the wildcard) ... then everything works. (而不是保持通配符)...然后一切正常。 But why? 但为什么?

Arrays.asList(action1, action2) will return a List<Action> . Arrays.asList(action1, action2)将返回List<Action> is(Arrays.asList(action1, action2)) will therefore return a Matcher<List<Action>> . is(Arrays.asList(action1, action2))将返回Matcher<List<Action>>

assertThat has the following signature: assert具有以下签名:

assertThat(T actual, Matcher<T> matcher)

So assertThat requires the following parameters in your case: 所以assertThat在你的情况下需要以下参数:

assertThat(List<Action>, Matcher<List<Action>>)

But your first parameter is a List<? extends Action> 但是你的第一个参数是List<? extends Action> List<? extends Action> And a List<Action> is completely different from a List<? extends Action> List<? extends Action> List<Action>List<? extends Action>完全不同List<? extends Action> List<? extends Action> . List<? extends Action> For example, you cannot put Action elements into a List<SomeSubClassOfAction> . 例如,您不能将Action元素放入List<SomeSubClassOfAction> This is why this won't work. 这就是为什么这不起作用的原因。

For details, see Angelika Langer's excellent site: http://www.angelikalanger.com/GenericsFAQ/FAQSections/Index.html 有关详细信息,请参阅Angelika Langer的优秀网站: http//www.angelikalanger.com/GenericsFAQ/FAQSections/Index.html

Your question was, why 你的问题是,为什么

@Override
public List<SomeSubClassOfAction> getActions()

is a legal Implementation of 是一个合法的实施

public List<? extends Action> getActions()

The Answer is covariant return . 答案是协变回报 Since Java1.5 subclasses are allowed to specialize the return of inherited methods. 由于允许Java1.5子类专门继承返回的继承方法。

But I wouldn't recommend having wildcard types in return parameters because it isn't client friendly. 但我不建议在返回参数中使用通配符类型,因为它不是客户端友好的。 See Generic wildcard types should not be used in return parameters and its quote from Effective Java 请参阅通用通配符类型不应用于返回参数及其来自Effective Java的引用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM