En aquest tema, aprendrem com utilitzar Mockito, una popular llibreria de mocking per a Java, juntament amb JUnit per crear tests més robustos i flexibles. Mockito ens permet crear mocks d'objectes per simular el comportament de les dependències en els nostres tests.
Què és Mockito?
Mockito és una llibreria de mocking per a Java que permet crear objectes simulats (mocks) per a les nostres proves unitàries. Els mocks ens permeten aïllar el codi que estem provant de les seves dependències, facilitant la detecció d'errors i la verificació del comportament del codi.
Configuració de Mockito
Abans de començar a utilitzar Mockito amb JUnit, hem d'afegir la dependència de Mockito al nostre projecte. Si estem utilitzant Maven, podem afegir la següent dependència al nostre pom.xml:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.11.2</version>
<scope>test</scope>
</dependency>Si estem utilitzant Gradle, podem afegir la següent línia al nostre build.gradle:
Creant Mocks amb Mockito
Per crear un mock amb Mockito, utilitzem la funció Mockito.mock(). A continuació, es mostra un exemple de com crear un mock i utilitzar-lo en un test de JUnit:
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class UserServiceTest {
@Test
void testGetUser() {
// Crear un mock de la classe UserRepository
UserRepository mockRepository = mock(UserRepository.class);
// Definir el comportament del mock
User mockUser = new User("John", "Doe");
when(mockRepository.findUserById(1)).thenReturn(mockUser);
// Crear una instància de la classe que estem provant
UserService userService = new UserService(mockRepository);
// Executar el mètode que estem provant
User result = userService.getUser(1);
// Verificar el resultat
assertEquals("John", result.getFirstName());
assertEquals("Doe", result.getLastName());
}
}Explicació del Codi
- Creació del Mock: Utilitzem
mock(UserRepository.class)per crear un mock de la classeUserRepository. - Definició del Comportament del Mock: Utilitzem
when(mockRepository.findUserById(1)).thenReturn(mockUser)per definir el comportament del mock. Quan es crida al mètodefindUserById(1), el mock retornarà l'objectemockUser. - Creació de la Classe a Provar: Creem una instància de
UserServicepassant-li el mockmockRepository. - Execució del Mètode a Provar: Cridem al mètode
getUser(1)deUserService. - Verificació del Resultat: Utilitzem
assertEqualsper verificar que el resultat és el que esperem.
Verificant Interaccions amb Mockito
Mockito també ens permet verificar que els mètodes dels mocks han estat cridats amb els paràmetres correctes. A continuació, es mostra un exemple de com fer-ho:
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class UserServiceTest {
@Test
void testGetUser() {
UserRepository mockRepository = mock(UserRepository.class);
User mockUser = new User("John", "Doe");
when(mockRepository.findUserById(1)).thenReturn(mockUser);
UserService userService = new UserService(mockRepository);
User result = userService.getUser(1);
assertEquals("John", result.getFirstName());
assertEquals("Doe", result.getLastName());
// Verificar que el mètode findUserById ha estat cridat amb el paràmetre 1
verify(mockRepository).findUserById(1);
}
}Explicació del Codi
- Verificació de la Interacció: Utilitzem
verify(mockRepository).findUserById(1)per verificar que el mètodefindUserByIddel mockmockRepositoryha estat cridat amb el paràmetre1.
Exercici Pràctic
Exercici
Crea un test per a la classe OrderService que utilitzi Mockito per simular el comportament de la seva dependència OrderRepository. Verifica que el mètode placeOrder crida al mètode saveOrder del OrderRepository amb l'ordre correcta.
class OrderService {
private final OrderRepository orderRepository;
public OrderService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
public void placeOrder(Order order) {
orderRepository.saveOrder(order);
}
}
interface OrderRepository {
void saveOrder(Order order);
}
class Order {
private final String product;
private final int quantity;
public Order(String product, int quantity) {
this.product = product;
this.quantity = quantity;
}
// Getters
public String getProduct() {
return product;
}
public int getQuantity() {
return quantity;
}
}Solució
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.Test;
class OrderServiceTest {
@Test
void testPlaceOrder() {
// Crear un mock de la classe OrderRepository
OrderRepository mockRepository = mock(OrderRepository.class);
// Crear una instància de la classe que estem provant
OrderService orderService = new OrderService(mockRepository);
// Crear una ordre de prova
Order order = new Order("Laptop", 1);
// Executar el mètode que estem provant
orderService.placeOrder(order);
// Verificar que el mètode saveOrder ha estat cridat amb l'ordre correcta
verify(mockRepository).saveOrder(order);
}
}Explicació del Codi
- Creació del Mock: Utilitzem
mock(OrderRepository.class)per crear un mock de la classeOrderRepository. - Creació de la Classe a Provar: Creem una instància de
OrderServicepassant-li el mockmockRepository. - Creació de l'Ordre de Prova: Creem una instància de
Orderamb els valors "Laptop" i 1. - Execució del Mètode a Provar: Cridem al mètode
placeOrder(order)deOrderService. - Verificació de la Interacció: Utilitzem
verify(mockRepository).saveOrder(order)per verificar que el mètodesaveOrderdel mockmockRepositoryha estat cridat amb l'ordreorder.
Conclusió
En aquest tema, hem après com utilitzar Mockito amb JUnit per crear mocks i verificar interaccions. Hem vist com configurar Mockito, crear mocks, definir el seu comportament i verificar que els mètodes dels mocks han estat cridats amb els paràmetres correctes. Aquests coneixements ens permetran escriure tests més robustos i flexibles, aïllant el codi que estem provant de les seves dependències.
Curs de JUnit
Mòdul 1: Introducció a JUnit
Mòdul 2: Anotacions Bàsiques de JUnit
- Entenent @Test
- Utilitzant @Before i @After
- Utilitzant @BeforeClass i @AfterClass
- Ignorant Tests amb @Ignore
Mòdul 3: Assertions a JUnit
Mòdul 4: Tests Parametritzats
- Introducció als Tests Parametritzats
- Creant Tests Parametritzats
- Utilitzant @ParameterizedTest
- Tests Parametritzats Personalitzats
Mòdul 5: Suites de Test
Mòdul 6: Mocking amb JUnit
Mòdul 7: Funcions Avançades de JUnit
Mòdul 8: Millors Pràctiques i Consells
- Escrivint Tests Efectius
- Organitzant el Codi de Test
- Desenvolupament Guiat per Tests (TDD)
- Integració Contínua amb JUnit
