【问题标题】:Need explanation : Generic friendliness to avoid casting, this is not anymore needed in Java 8需要解释:避免强制转换的通用友好性,在 Java 8 中不再需要
【发布时间】:2018-01-07 09:51:17
【问题描述】:
* @deprecated With Java 8 this method will be removed in Mockito 3.0. This method is only used for generic
 * friendliness to avoid casting, this is not anymore needed in Java 8.
 */
public static <T> List<T> anyListOf(Class<T> clazz) {
    return anyList();
}

我正在查看 Mockito 源代码并遇到了这个已弃用的方法,任何人都可以解释在 Java 8 中是如何处理这个问题的。如果我可以在不使用该方法作为参数的情况下调用泛型方法的示例,将不胜感激为它。

@Test
public void getDataTest() {
    when(dataSetDao.getDataSetList()).thenReturn(getMockDataSetList());
    when(serviceUtil.getDataFromEndpoint(anyInt(), anyList(), anyString(), any(TypeToken.class), anyString())).thenReturn(getMockDataList());
    List<Data> dataList = noaaDataService.getData();
    verify(serviceUtil, times(11)).getDataFromEndpoint(anyInt(), anyList(), anyString(), any(TypeToken.class), anyString());
    assertEquals(11, dataList.size());

}

private <T> List<T> getMockDataList() {
    List<Data> dataList = new ArrayList<>();
    for (int i = 0; i < 1; ++i) {
        dataList.add(new Data());
    }
    return (List<T>) dataList;
}

无法解析方法 'thenReturn(java.util.List)。这是我以上述方式调用方法时收到的错误。

如果在 Java 8 中改进了类型推断,有人可以解释为什么我会收到此错误。

被调用的方法:

/**
 * Generic method to fetch data from rest endpoint.
 *
 * @param offset       Default should be 0, recursive call in place would increase it till we have fetched all the records.
 * @param dataList     List to be returned and passed on to the recursive call.
 * @param postFixUrl   End point to be used.
 * @param responseType Used to convert the response into json, need this so that we will know the generic type at compile time.
 * @param <T>          Entity for which we are fetching the data.
 * @param arguments    Arguments to be passed to the uri.
 * @return A list of T derived from the response.
 */
public <T> List<T> getDataFromEndpoint(
    int offset, List<T> dataList, String postFixUrl,
    TypeToken<ArrayList<T>> responseType, String arguments)

临时解决这个问题,有没有更好的方法来做到这一点。

@Test
public void getDataTest() {
    when(dataSetDao.getDataSetList()).thenReturn(getMockDataSetList());
    when(serviceUtil.getDataFromEndpoint(anyInt(), anyList(), anyString(), any(TypeToken.class), anyString())).thenReturn(getMockDataList(Data.class));
    List<Data> dataList = noaaDataService.getData();
    verify(serviceUtil, times(11)).getDataFromEndpoint(anyInt(), anyList(), anyString(), any(TypeToken.class), anyString());
    assertEquals(11, dataList.size());

}

private <T> List<T> getMockDataList(T type) {
    List<Data> dataList = new ArrayList<>();
    for (int i = 0; i < 1; ++i) {
        dataList.add(new Data());
    }
    return (List<T>) dataList;
}

提前致谢。

【问题讨论】:

  • Java 8 中改进了类型推断。
  • 我相信您将 anyListOf() 调用替换为 anyList() 调用。
  • 我之前尝试过,但它给了我一个错误,我已经更新了问题以反映这一点。
  • 在 8 中,包含方法参数以找出目标类型,看起来这就是这里发生的事情
  • 抱歉延迟回复,我已更新问题以使用代码而不是图像。

标签: java generics java-8 mockito


【解决方案1】:

问题在于您的getDataFromEndpoint(...) 方法的返回类型是通用的,并且它的T 类型参数仅从通过提供的方法参数的返回类型推断出来

<T> T Mockito.any(Class<T> type)

当您传入一个类文字 TypeToken.class 时,它只是 Class&lt;TypeToken&gt;,而不是所需的类型 Class&lt;TypeToken&lt;Data&gt;&gt;

因此,serviceUtil.getDataFromEndpoint(...) 的推断类型将是 List&lt;Object&gt;,而不是所需的 List&lt;Data&gt;。因此,您的下一步将失败,因为

返回的推断类型
when(...)

将是

OngoingStubbing<List<Object>>

而不是想要的

OngoingStubbing<List<Data>>

只接受List&lt;Object&gt;,而不接受List&lt;Data&gt;,因为List&lt;Data&gt;不是List&lt;Object&gt;的子类型。

解决方案是为泛型serviceUtil.getDataFromEndpoint(...)提供类型见证

serviceUtil.<Data> getDataFromEndpoint(...)

并且您的代码应该使用所有主要编译器编译,无论是 JDK、Eclipse、IntelliJ IDEA 还是 Netbeans。 Generalized target-type inference 通常运行良好,但在这种情况下,您提供了错误的参数以使其正常运行。

【讨论】:

  • 感谢您的回答,这解决了问题。很高兴知道我们可以通过这种方式调用泛型方法。
猜你喜欢
  • 2014-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多