java - 使用 mockito 模拟使用通配符返回泛型的方法

标签 java generics mockito

我使用的是 mockito 1.9.5。 我有以下代码:

public class ClassA  {

public List<? extends MyInterface> getMyInterfaces() {
    return null;
}

public static void testMock() {
    List<MyInterface> interfaces = new ArrayList<>();
    ClassA classAMock = mock(ClassA.class);
    when(classAMock.getMyInterfaces()).thenReturn(interfaces);      
}

我得到一个编译错误 thenReturn(interfaces) 说:

"The method thenReturn(List<capture#1-of ? extends MyInterface>) in the type 
 OngoingStubbing<List<capture#1-of ? extends MyInterface>> is not applicable for the arguments 
 (List<MyInterface>)"

但是,当我使用 mockito 的 thenAnswer 方法时,我没有收到错误消息。谁能告诉我发生了什么事?为什么我在使用 thenReturn 方法时会收到错误消息? 当 ClassA 由第三方提供且无法修改时,是否有其他方法可以解决此问题?

最佳答案

编辑:从 Mockito 1.10.x 开始,嵌入在类中的泛型类型现在被 Mockito 用于深度 stub 。 IE。

public interface A<T extends Observer & Comparable<? super T>>  {
  List<? extends B> bList();
  T observer();
}

B b = deep_stubbed.bList().iterator().next(); // returns a mock of B ; mockito remebers that A returns a List of B
Observer o = deep_stubbed.observer(); // mockito can find that T super type is Observer
Comparable<? super T> c = deep_stubbed.observer(); // or that T implements Comparable

Mockito 尽力获取编译器嵌入的类型信息,但是当应用删除时,mockito 只能返回 Object 的模拟。


原创:嗯,这更多是泛型的问题,而不是 Mockito 的问题。对于泛型,您应该阅读 Angelika Langer 在它们上写的内容。对于当前主题,即通配符,请阅读 section .

但简而言之,您可以使用 Mockito 的其他语法来帮助您解决当前的情况:

doReturn(interfaces).when(classAMock).getMyInterfaces();

或者使用 BDD 别名:

willReturn(interfaces).given(classAMock).getMyInterfaces();

尽管如此,您可以编写更通用友好的包装器。这将有助于 future 的开发人员使用相同的第 3 方 API。


附带说明:您不应该模拟您不拥有的类型,这可能会导致许多错误和问题。相反,你应该有一些包装。例如 DAO 和存储库就代表了这样的想法,人们将模拟 DAO 或存储库接口(interface),而不是 JDBC/JPA/hibernate 的东西。有很多关于此的博客文章:

关于java - 使用 mockito 模拟使用通配符返回泛型的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15942880/

相关文章:

java - 将二叉搜索树打印为单个字符串

java - 如何将单个实现绑定(bind)到 Guice 中的多个通用接口(interface)?

spring - 使用mockmvc和junit添加csrf token

java - Powermock 构造函数模拟对实例化对象没有影响

javascript - MGWT ScrollPanel.scrollTo(0, y) 导致无法读取未定义的属性 'style'

Java Switch菜单错误以及如何从另一个类调用方法

java - List<Dog> 是 List<Animal> 的子类吗?为什么 Java 泛型不是隐式多态的?

未强制执行 Java 接口(interface)

android - 尝试模拟 NavController 时出错

java - 无法在 IntelliJ IDEA 中添加 maven 模块