DEV Community

Hugo Marques
Hugo Marques

Posted on

Testando das trincheiras: Como criar mocks e stubs dinâmico com mockito em java

Esse vai ser curtinho. Hoje eu estava tentando testar uma classe que segue o seguinte comportamento:

Book book = bookManager.getBook(id);
book.getId();
Enter fullscreen mode Exit fullscreen mode

Por vários motivos que não vêm ao caso agora, imagine que você não consegue construir o objeto BookManager e também não consegue criar um FakeBook para injetar o ID conforme você deseja.

Pois bem, eu lembrei que era possível criar um mock dinâmico usando Answer do Mockito.

Solução: Um mock dinâmico

A solução fica assim:

@ExtendWith(MockitoExtension.class)
public class MyBookManagerTest {

@Mock 
private BookManager bookManager;
@Mock 
private Book book;

    @Test
    public void testMyMethod() {
        // Define the behavior of the bookManager mock
        when(bookManager.getBook(anyInt())).thenAnswer(new Answer<Book>() {
            @Override
            public Book answer(InvocationOnMock invocation) throws Throwable {
                Object[] args = invocation.getArguments();
                int id = (Integer) args[0];
                when(book.getId()).thenReturn(id);
                return book;
            }
        });
        // Use the mock in the test
        Book book = bookManager.getBook(12345);
        // Verify the behavior of the mock
        assertEquals(12345, book.getId());
    }
}
Enter fullscreen mode Exit fullscreen mode

Note que, ao definirmos o comportamento do BookManager, retornamos uma Answer. Nessa Answer, capturamos o parâmetro passado (veja como usamos a invocation) e o configuramos no mock Book para ser retornado quando fizermos a chamada book.getId().

Dessa forma, em vez de definirmos o mock diversas vezes, podemos definir apenas uma vez e fazer várias chamadas:

// Use the mock in the test
        Book book = bookManager.getBook(12345);
        // Verify the behavior of the mock
        assertEquals(12345, book.getId());

// Esse aqui também funciona porque o nosso mock é configurável
        Book book = bookManager.getBook(6789);
        // Verify the behavior of the mock
        assertEquals(6789, book.getId());
Enter fullscreen mode Exit fullscreen mode

Simplificando: Java 8 + Lambdas 🥰

Se usarmos lambdas em vez da anonymous classe, o nosso exemplo fica ainda mais simples:

        when(bookManager.getBook(anyInt()))
.thenAnswer(invocation -> {
            int id = invocation.getArgument(0);
            when(book.getId()).thenReturn(id);
            return book;
        });
Enter fullscreen mode Exit fullscreen mode

É isso, essa foi direto das trincheiras. Normalmente, eu gosto de evitar mocks se possível e tento usar os objetos reais. No meu caso específico criar o objeto ia ser um trampo do cão e aí eu decidi usar a ferramenta pra simplicar a minha vida.

Keep coding! 💻

Top comments (2)

Collapse
 
kauanmocelin profile image
Kauan Mocelin

Recurso interessante pra lidar com códigos legados quando está tudo muito acoplado, aprendi mais uma Hugo!

Collapse
 
tmsanghoclaptrinh profile image
Sáng Minh Trần