6

我在使用 mockito 模拟方法时遇到问题,如下所示:

Map<Foo, ? extends Collection<Bar>> getValue();

以下是我在测试中使用它的方式:

model = Mockito.mock(Model.class);
Map<Foo, List<Bar>> value = new HashMap<Foo, List<Bar>>();
Mockito.when(model.getValue()).thenReturn(value);

它给出了以下错误:

错误:找不到合适的方法thenReturn(Map<Foo,List<Bar>>)

4

3 回答 3

11

您可以使用以下内容:

model = Mockito.mock(Model.class);
final Map<Foo, List<Bar>> value = new HashMap<Foo, List<Bar>>();

Mockito.when(model.getValue()).thenAnswer(new Answer<Map<Foo, List<Bar>>> () {
  public Map<Foo, List<Bar>> answer(InvocationOnMock invocation) throws Throwable {
    return value;
  }
});

以上可以使用 lambda 缩短为:

Mockito.when(model.getValue()).thenAnswer(invocationOnMock -> value)
于 2013-11-15T17:21:30.653 回答
4

发生此错误是因为编译器无法保证返回的映射的值类型getValue实际上是List<Bar>. 该类型的Map<Foo, ? extends Collection>意思是“某个未知Map类型的实现”。FooCollection

这是一个很好的例子,说明了为什么不鼓励在返回类型中使用通配符,因为它们通常会通过掩盖有关返回内容的泛型类型信息来抑制调用者(相反,鼓励在方法参数中使用通配符,因为它使调用者的事情变得更容易)。如果可能的话,我建议去掉通配符:

Map<Foo, Collection<Bar>> getValue();

并使用:

model = Mockito.mock(Model.class);
Map<Foo, Collection<Bar>> value = new HashMap<Foo, Collection<Bar>>();
Mockito.when(model.getValue()).thenReturn(value);

如果您无法更改方法的返回类型,则可以使用“捕获助手”方法进行测试:

private <T extends Collection<Bar>> test(Map<Foo, T> actual) {
    Map<Foo, T> expected = new HashMap<Foo, T>();
    Mockito.when(actual).thenReturn(expected);
}

...

model = Mockito.mock(Model.class);
test(model.getValue()); // T is resolved to wildcard capture

当然,这是非常有限的,因为您只能在不知道是什么的情况下测试空地图T

于 2013-06-28T01:14:17.503 回答
1

如果您不想编写辅助函数,使用doReturn...when也可以,就像这样(尽管它不是类型安全的):

Mockito.doReturn(value).when(model).getValue();
public class Test {
    interface Model {
        Map<Foo, ? extends Collection<Bar>> getValue();
    }
    class Bar {}
    class Foo {}

    public static void main(String[] args) {
        Model model = Mockito.mock(Model.class);
        Map<Foo, List<Bar>> value = new HashMap<Foo, List<Bar>>();

//      when(model.getValue()).thenReturn(value); // won't compile
        doReturn(value).when(model).getValue();

        System.out.println(model.getValue());
    }
}
于 2017-02-05T04:15:02.817 回答