Solución:
El problema genérico anidado se puede evitar con la anotación @Captor:
public class Test{
@Mock
private Service service;
@Captor
private ArgumentCaptor<ArrayList<SomeType>> captor;
@Before
public void init(){
MockitoAnnotations.initMocks(this);
}
@Test
public void shouldDoStuffWithListValues() {
//...
verify(service).doStuff(captor.capture()));
}
}
Sí, este es un problema genérico general, no específico de un mockito.
No hay ningún objeto de clase para ArrayList<SomeType>
y, por lo tanto, no puede pasar de forma segura un objeto de este tipo a un método que requiera una Class<ArrayList<SomeType>>
.
Puede convertir el objeto al tipo correcto:
Class<ArrayList<SomeType>> listClass =
(Class<ArrayList<SomeType>>)(Class)ArrayList.class;
ArgumentCaptor<ArrayList<SomeType>> argument = ArgumentCaptor.forClass(listClass);
Esto le dará algunas advertencias sobre lanzamientos inseguros y, por supuesto, su ArgumentCaptor realmente no puede diferenciar entre ArrayList<SomeType>
y ArrayList<AnotherType>
sin quizás inspeccionar los elementos.
(Como se mencionó en la otra respuesta, si bien este es un problema genérico general, existe una solución específica de Mockito para el problema de seguridad de tipos con el @Captor
anotación. Todavía no puede distinguir entre un ArrayList<SomeType>
y un ArrayList<OtherType>
.)
Editar:
Eche también un vistazo a tenshis comentario. Puedes cambiar el código original de Paŭlo Ebermann a este (mucho más simple)
final ArgumentCaptor<List<SomeType>> listCaptor
= ArgumentCaptor.forClass((Class) List.class);
Si no le teme a la antigua semántica de estilo java (genérico no seguro para tipos), esto también funciona y es simple:
ArgumentCaptor<List> argument = ArgumentCaptor.forClass(List.class);
verify(subject.method(argument.capture()); // run your code
List<SomeType> list = argument.getValue(); // first captured List, etc.