为什么在嘲笑2中使用“ doAnswer”时getArgument()不会隐式转换?

时间:2019-01-25 12:48:12

标签: generics java-8 casting mockito

所以现在我正在从Mockito 1. *迁移到2. *,但我不明白为什么在doAnswer中使用getArgument()时为什么会有转换问题。我的意思是,当我尝试在其他方法参数中调用getArgument()或尝试在检索到的对象上链接方法时。 这是适用于嘲笑1. *的代码

 doAnswer(invocation -> {
            try (InputStream inputStream = invocation.getArgumentAt(0, SomeResource.class).getResource().getInputStream()) {
                IOUtils.copy(inputStream, invocation.getArgumentAt(1, OutputStream.class));
            }
        return null;
        }).when(mockedService).downloadFile(any(), any());

迁移到2. *后,将getArgumentAt()更改为getArgument()失败,因为找不到带有类型的“ getResource()”方法。由于类型不兼容,从调用中获取第二个参数也不起作用。

doAnswer(invocation -> {
            try (InputStream inputStream = invocation.getArgument(0).getResource().getInputStream()) {
                IOUtils.copy(inputStream, invocation.getArgument(1));
            }
        return null;
        }).when(mockedService).downloadFile(any(), any());

我不得不更改为在第二个参数中显式强制转换,或显式保存为新引用,第一个参数相同。 该代码有效:

doAnswer(invocation -> {
    final SomeResource input = invocation.getArgument(0);
    final OutputStream outputStream = invocation.getArgument(1);
    try (InputStream inputStream = input.getResource().getInputStream()) {
        IOUtils.copy(inputStream, outputStream);
    }
    return null;
}).when(mockedService).downloadFile(any(), any());

我不知道为什么。

1 个答案:

答案 0 :(得分:0)

方法getArgument是一种通用方法。它具有以下签名:

<T> T getArgument(int index)

请参见javadoc

直到Java 8才添加了Generalized Target-Type Inference,并且通常将返回类型类用作参数之一(例如在使用Mockito 1. *的示例中),这才成为可能。

因此,当您将结果分配给具体类型的变量时,不需要强制转换,因为可以推断出它。当传递给IOUtils.copy()时,它无法推断单个具体类型,因为copy方法已重载。如果将其传递给未重载的方法,则无需显式强制转换即可工作。