如何用mockito捕获特定types的列表

有没有办法使用mockitos ArgumentCaptore捕获特定types的列表。 这不起作用:

ArgumentCaptor<ArrayList<SomeType>> argument = ArgumentCaptor.forClass(ArrayList.class); 

使用@Captor批注可以避免嵌套的generics问题:

 @RunWith(MockitoJUnitRunner.class) public class Test{ @Mock private Service service; @Captor private ArgumentCaptor<ArrayList<SomeType>> captor; @Test public void shouldDoStuffWithListValues() { //... verify(service).doStuff(captor.capture())); } } 

是的,这是一个普遍的generics问题,不是mockito特定的。

ArrayList<SomeType>没有类对象,因此您无法安全地将此类对象传递给需要Class<ArrayList<SomeType>>

您可以将对象转换为正确的types:

 Class<ArrayList<SomeType>> listClass = (Class<ArrayList<SomeType>>)(Class)ArrayList.class; ArgumentCaptor<ArrayList<SomeType>> argument = ArgumentCaptor.forClass(listClass); 

这将给出一些关于不安全转换的警告,当然你的ArgumentCaptor也不能真正区分ArrayList<SomeType>ArrayList<AnotherType>而不检查元素。

(正如在另一个答案中提到的那样,虽然这是一个generics的问题,但是对于types安全问题,使用@Captor注解来解决Mockito特定的问题,仍然无法区分ArrayList<SomeType>ArrayList<OtherType> 。)

编辑:

再看看tenshi的评论。 您可以将PaŭloEbermann的原始代码更改为(更简单)

 final ArgumentCaptor<List<SomeType>> listCaptor = ArgumentCaptor.forClass((Class) List.class); 

如果你不害怕旧的Java风格(非types安全通用)语义,这也可以工作,并且相当简单(r):

 ArgumentCaptor<List> argument = ArgumentCaptor.forClass(List.class); List<SomeType> list = argument.getValue(); // first captured List, etc. 
 List<String> mockedList = mock(List.class); List<String> l = new ArrayList(); l.add("someElement"); mockedList.addAll(l); ArgumentCaptor<List> argumentCaptor = ArgumentCaptor.forClass(List.class); verify(mockedList).addAll(argumentCaptor.capture()); List<String> capturedArgument = argumentCaptor.<List<String>>getValue(); assertThat(capturedArgument, hasItem("someElement")); 

我在Android应用程序中遇到了与testing活动相同的问题。 我使用了ActivityInstrumentationTestCase2MockitoAnnotations.initMocks(this); 没有工作。 我分别用另外一个类来解决这个问题。 例如:

 class CaptorHolder { @Captor ArgumentCaptor<Callback<AuthResponse>> captor; public CaptorHolder() { MockitoAnnotations.initMocks(this); } } 

那么,在活动testing方法中:

 HubstaffService hubstaffService = mock(HubstaffService.class); fragment.setHubstaffService(hubstaffService); CaptorHolder captorHolder = new CaptorHolder(); ArgumentCaptor<Callback<AuthResponse>> captor = captorHolder.captor; onView(withId(R.id.signInBtn)) .perform(click()); verify(hubstaffService).authorize(anyString(), anyString(), captor.capture()); Callback<AuthResponse> callback = captor.getValue();