在我的测试中,我有以下内容:

when(client.runTask(anyString(), anyString(), isA(Iterable.class)).thenReturn(...)
isA(Iterable.class)产生警告,它需要未经检查的转换才能符合Iterable<Integer>。那是什么语法?
isA(Iterable<Integer>.class)
isA((Iterable<Integer>)Iterable.class

不工作。

有什么建议么?

最佳答案

Mockito/Hamcrest和泛型类

是的,这是Mockito/Hamcrest的普遍问题。通常,将isA()与泛型类一起使用会产生警告。

对于最常见的通用类,存在预定义的Mockito匹配器:anyList()anyMap()anySet()anyCollection()

意见建议:

Mockito 2.1.0中的anyIterable()

Mockito 2.1.0添加了新的anyIterable()方法来匹配Iterables:

when(client.runTask(anyString(), anyString(), anyIterable()).thenReturn(...)

在Eclipse中忽略

如果您只是想摆脱Eclipse中的警告。自Eclipse Indigo以来存在选项:



使用@SuppressWarnings快速修复

如果您只有一次问题,我建议您这样做。我个人不记得曾经需要isA(Iterable.class)

正如Daniel Pryden所说,您可以将@SuppressWarnings限制为局部变量或辅助方法。

对TypeToken使用通用的isA()匹配器

这样可以彻底解决问题。但这有两个缺点:
  • 语法不太漂亮,可能会使某些人感到困惑。
  • 您对提供TypeToken类的库有其他依赖性。在这里,我使用了TypeToken class from Guava。 Gson中还有一个TypeToken类,而JAX-RS中还有一个GenericType

  • 使用通用匹配器:
    import static com.arendvr.matchers.InstanceOfGeneric.isA;
    import static org.mockito.ArgumentMatchers.argThat;
    
    // ...
    
    when(client.runTask(anyString(), anyString(), argThat(isA(new TypeToken<Iterable<Integer>>() {}))))
                .thenReturn(...);
    

    通用匹配器类:
    package com.arendvr.matchers;
    
    import com.google.common.reflect.TypeToken;
    import org.mockito.ArgumentMatcher;
    
    public class InstanceOfGeneric<T> implements ArgumentMatcher<T> {
        private final TypeToken<T> typeToken;
    
        private InstanceOfGeneric(TypeToken<T> typeToken) {
            this.typeToken = typeToken;
        }
    
        public static <T> InstanceOfGeneric<T> isA(TypeToken<T> typeToken) {
            return new InstanceOfGeneric<>(typeToken);
        }
    
        @Override
        public boolean matches(Object item) {
            return item != null && typeToken.getRawType().isAssignableFrom(item.getClass());
        }
    }
    

    07-24 09:50
    查看更多