En este tema, aprenderemos cómo integrar Mockito con JUnit para crear pruebas unitarias más efectivas y robustas. Mockito es una biblioteca de Java que permite crear objetos simulados (mocks) para pruebas unitarias. Esto es especialmente útil cuando queremos aislar el código que estamos probando de sus dependencias.

Contenido

  1. ¿Qué es Mockito?
  2. Configuración de Mockito con JUnit
  3. Creando Mocks con Mockito
  4. Inyectando Mocks en el Código
  5. Verificando Interacciones
  6. Ejemplo Práctico
  7. Ejercicios Prácticos

  1. ¿Qué es Mockito?

Mockito es una biblioteca de Java que permite crear objetos simulados (mocks) para pruebas unitarias. Los mocks son objetos que imitan el comportamiento de objetos reales en un entorno controlado. Esto es útil para probar el comportamiento de una clase sin depender de sus dependencias externas.

  1. Configuración de Mockito con JUnit

Para usar Mockito con JUnit, primero necesitamos agregar las dependencias necesarias a nuestro proyecto. Si estás usando Maven, agrega las siguientes dependencias a tu archivo pom.xml:

<dependencies>
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>3.11.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.7.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Si estás usando Gradle, agrega las siguientes líneas a tu archivo build.gradle:

dependencies {
    testImplementation 'org.mockito:mockito-core:3.11.2'
    testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.7.2'
}

  1. Creando Mocks con Mockito

Para crear un mock con Mockito, usamos el método Mockito.mock(). Aquí hay un ejemplo básico:

import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class MyServiceTest {

    @Test
    public void testMyService() {
        // Crear un mock de la clase Dependency
        Dependency dependencyMock = Mockito.mock(Dependency.class);

        // Definir el comportamiento del mock
        Mockito.when(dependencyMock.someMethod()).thenReturn("Mocked Response");

        // Usar el mock en la clase que estamos probando
        MyService myService = new MyService(dependencyMock);
        String result = myService.performAction();

        // Verificar el resultado
        assertEquals("Mocked Response", result);
    }
}

  1. Inyectando Mocks en el Código

En lugar de crear manualmente los mocks, podemos usar anotaciones para simplificar el proceso. Mockito proporciona la anotación @Mock para crear mocks y @InjectMocks para inyectarlos en la clase que estamos probando.

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;

public class MyServiceTest {

    @Mock
    private Dependency dependencyMock;

    @InjectMocks
    private MyService myService;

    @BeforeEach
    public void setUp() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    public void testMyService() {
        // Definir el comportamiento del mock
        when(dependencyMock.someMethod()).thenReturn("Mocked Response");

        // Usar el mock en la clase que estamos probando
        String result = myService.performAction();

        // Verificar el resultado
        assertEquals("Mocked Response", result);
    }
}

  1. Verificando Interacciones

Además de definir el comportamiento de los mocks, también podemos verificar que ciertos métodos fueron llamados con los argumentos correctos. Esto se hace usando el método Mockito.verify().

import static org.mockito.Mockito.verify;

@Test
public void testMyService() {
    // Definir el comportamiento del mock
    when(dependencyMock.someMethod()).thenReturn("Mocked Response");

    // Usar el mock en la clase que estamos probando
    String result = myService.performAction();

    // Verificar el resultado
    assertEquals("Mocked Response", result);

    // Verificar que el método someMethod() fue llamado una vez
    verify(dependencyMock).someMethod();
}

  1. Ejemplo Práctico

Vamos a ver un ejemplo más completo que incluye la creación de mocks, la inyección de dependencias y la verificación de interacciones.

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class UserServiceTest {

    @Mock
    private UserRepository userRepositoryMock;

    @InjectMocks
    private UserService userService;

    @BeforeEach
    public void setUp() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    public void testGetUser() {
        // Definir el comportamiento del mock
        User mockUser = new User("John", "Doe");
        when(userRepositoryMock.findUserById(1)).thenReturn(mockUser);

        // Usar el mock en la clase que estamos probando
        User result = userService.getUser(1);

        // Verificar el resultado
        assertEquals("John", result.getFirstName());
        assertEquals("Doe", result.getLastName());

        // Verificar que el método findUserById() fue llamado una vez con el argumento 1
        verify(userRepositoryMock).findUserById(1);
    }
}

  1. Ejercicios Prácticos

Ejercicio 1: Crear y Usar Mocks

  1. Crea una clase Calculator con un método add(int a, int b) que devuelve la suma de a y b.
  2. Crea una clase CalculatorService que tenga una dependencia de Calculator.
  3. Escribe una prueba unitaria para CalculatorService usando Mockito para simular el comportamiento de Calculator.

Ejercicio 2: Verificar Interacciones

  1. Modifica la clase CalculatorService para que tenga un método calculateSum(int a, int b) que use el método add de Calculator.
  2. Escribe una prueba unitaria para calculateSum que verifique que el método add de Calculator fue llamado con los argumentos correctos.

Soluciones

Solución Ejercicio 1

// Calculator.java
public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
}

// CalculatorService.java
public class CalculatorService {
    private Calculator calculator;

    public CalculatorService(Calculator calculator) {
        this.calculator = calculator;
    }

    public int calculateSum(int a, int b) {
        return calculator.add(a, b);
    }
}

// CalculatorServiceTest.java
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;

public class CalculatorServiceTest {

    @Mock
    private Calculator calculatorMock;

    @InjectMocks
    private CalculatorService calculatorService;

    @BeforeEach
    public void setUp() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    public void testCalculateSum() {
        // Definir el comportamiento del mock
        when(calculatorMock.add(2, 3)).thenReturn(5);

        // Usar el mock en la clase que estamos probando
        int result = calculatorService.calculateSum(2, 3);

        // Verificar el resultado
        assertEquals(5, result);
    }
}

Solución Ejercicio 2

import static org.mockito.Mockito.verify;

@Test
public void testCalculateSum() {
    // Definir el comportamiento del mock
    when(calculatorMock.add(2, 3)).thenReturn(5);

    // Usar el mock en la clase que estamos probando
    int result = calculatorService.calculateSum(2, 3);

    // Verificar el resultado
    assertEquals(5, result);

    // Verificar que el método add() fue llamado una vez con los argumentos 2 y 3
    verify(calculatorMock).add(2, 3);
}

Conclusión

En este tema, hemos aprendido cómo usar Mockito con JUnit para crear pruebas unitarias más efectivas. Hemos cubierto cómo configurar Mockito, crear mocks, inyectar mocks en el código, y verificar interacciones. Además, hemos visto un ejemplo práctico y proporcionado ejercicios para reforzar los conceptos aprendidos. Con estas herramientas, estarás mejor preparado para escribir pruebas unitarias robustas y mantener un código de alta calidad.

© Copyright 2024. Todos los derechos reservados