Question

I have this TestNG test method code:

@InjectMocks
private FilmeService filmeService = new FilmeServiceImpl();

@Mock
private FilmeDAO filmeDao;

@BeforeMethod(alwaysRun=true)
public void injectDao() {
    MockitoAnnotations.initMocks(this);
}

//... another tests here

@Test
public void getRandomEnqueteFilmes() {
    @SuppressWarnings("unchecked")
    List<Filme> listaFilmes = mock(List.class);

    when(listaFilmes.get(anyInt())).thenReturn(any(Filme.class));
    when(filmeDao.listAll()).thenReturn(listaFilmes);

    List<Filme> filmes = filmeService.getRandomEnqueteFilmes();

    assertNotNull(filmes, "Lista de filmes retornou vazia");
    assertEquals(filmes.size(), 2, "Lista não retornou com 2 filmes");
}

And I'm getting a "org.mockito.exceptions.misusing.InvalidUseOfMatchersException: Invalid use of argument matchers! 0 matchers expected, 1 recorded:" in the call of listAll() method in this code:

@Override
public List<Filme> getRandomEnqueteFilmes() {
    int indice1, indice2 = 0;
    List<Filme> filmesExibir = new ArrayList<Filme>();
    List<Filme> filmes = dao.listAll();

    Random randomGenerator = new Random();
    indice1 = randomGenerator.nextInt(5);
    do {
        indice2 = randomGenerator.nextInt(5);
    } while(indice1 == indice2);

    filmesExibir.add(filmes.get(indice1));
    filmesExibir.add(filmes.get(indice2));

    return filmesExibir;
}

I'm prety sure I'm missing something here but I don't know what it is! Someone help?

Was it helpful?

Solution

when(listaFilmes.get(anyInt())).thenReturn(any(Filme.class));

There's your problem. You can't use any in a return value. any is a Matcher—it's used to match parameter values for stubbing and verification—and doesn't make sense in defining a return value for a call. You'll need to explicitly return a Filme instance, or leave it null (which is the default behavior, which would defeat the point of stubbing).

I should note that it's often a good idea to use a real List instead of a mock List. Unlike custom code you've developed, List implementations are well-defined and well-tested, and unlike mock Lists a real List is very unlikely to break if you refactor your system under test to call different methods. It's a matter of style and testing philosophy, but you may find it advantageous just to use a real List here.


Why would the above rule cause that exception? Well, this explanation breaks some of Mockito's abstractions, but matchers don't behave like you think they might—they record a value onto a secret ThreadLocal stack of ArgumentMatcher objects and return null or some other dummy value, and in the call to when or verify Mockito sees a non-empty stack and knows to use those Matchers in preference to actual argument values. As far as Mockito and the Java evaluation order are concerned, your code looks like the following:

when(listaFilmes.get(anyInt())).thenReturn(null);
when(filmeDao.listAll(any())).thenReturn(listaFilmes); // nonsense

Naturally Mockito sees an any matcher, and listAll doesn't take an argument, so there are 0 matchers expected, 1 recorded.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top