En aquest tema, aprendrem com verificar les interaccions entre els mocks i els objectes reals utilitzant Mockito amb JUnit. La verificació d'interaccions és crucial per assegurar-nos que els nostres mocks es comporten com esperem durant les proves.
Objectius
- Entendre la importància de verificar interaccions.
- Aprendre a utilitzar les funcions de verificació de Mockito.
- Veure exemples pràctics de verificació d'interaccions.
Importància de Verificar Interaccions
Quan fem servir mocks en les nostres proves, no només ens interessa el resultat final, sinó també com s'ha arribat a aquest resultat. Verificar les interaccions ens permet assegurar-nos que els mètodes dels mocks s'han cridat amb els arguments correctes i en l'ordre esperat.
Funcions de Verificació de Mockito
Mockito proporciona diverses funcions per verificar interaccions. Les més comunes són:
verify(mock)
: Verifica que un mètode del mock s'ha cridat.verify(mock, times(n))
: Verifica que un mètode del mock s'ha cridat exactamentn
vegades.verify(mock, never())
: Verifica que un mètode del mock no s'ha cridat mai.verify(mock, atLeast(n))
: Verifica que un mètode del mock s'ha cridat almenysn
vegades.verify(mock, atMost(n))
: Verifica que un mètode del mock s'ha cridat com a màximn
vegades.
Exemple Pràctic
Escenari
Suposem que tenim una classe UserService
que depèn d'una interfície UserRepository
per obtenir informació dels usuaris. Volem verificar que el mètode findUserById
de UserRepository
s'ha cridat correctament.
Codi
// UserService.java public class UserService { private UserRepository userRepository; public UserService(UserRepository userRepository) { this.userRepository = userRepository; } public User getUserById(int id) { return userRepository.findUserById(id); } } // UserRepository.java public interface UserRepository { User findUserById(int id); } // UserServiceTest.java import static org.mockito.Mockito.*; import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class UserServiceTest { private UserRepository userRepository; private UserService userService; @BeforeEach public void setUp() { userRepository = mock(UserRepository.class); userService = new UserService(userRepository); } @Test public void testGetUserById() { User user = new User(1, "John Doe"); when(userRepository.findUserById(1)).thenReturn(user); User result = userService.getUserById(1); assertEquals(user, result); verify(userRepository).findUserById(1); // Verifica que el mètode s'ha cridat una vegada } }
Explicació del Codi
- Mocking: Utilitzem
mock(UserRepository.class)
per crear un mock deUserRepository
. - Configuració: Utilitzem
when(userRepository.findUserById(1)).thenReturn(user)
per definir el comportament del mock. - Verificació: Utilitzem
verify(userRepository).findUserById(1)
per verificar que el mètodefindUserById
s'ha cridat amb l'argument1
.
Exercicis Pràctics
Exercici 1
Crea una classe OrderService
que depengui d'una interfície OrderRepository
. Escriu una prova que verifiqui que el mètode saveOrder
de OrderRepository
s'ha cridat exactament una vegada quan es guarda una comanda.
Solució
// OrderService.java public class OrderService { private OrderRepository orderRepository; public OrderService(OrderRepository orderRepository) { this.orderRepository = orderRepository; } public void saveOrder(Order order) { orderRepository.saveOrder(order); } } // OrderRepository.java public interface OrderRepository { void saveOrder(Order order); } // OrderServiceTest.java import static org.mockito.Mockito.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class OrderServiceTest { private OrderRepository orderRepository; private OrderService orderService; @BeforeEach public void setUp() { orderRepository = mock(OrderRepository.class); orderService = new OrderService(orderRepository); } @Test public void testSaveOrder() { Order order = new Order(1, "Product A"); orderService.saveOrder(order); verify(orderRepository).saveOrder(order); // Verifica que el mètode s'ha cridat una vegada } }
Exercici 2
Modifica la prova anterior per verificar que el mètode saveOrder
no s'ha cridat mai quan es passa una comanda nul·la.
Solució
@Test public void testSaveOrderWithNull() { orderService.saveOrder(null); verify(orderRepository, never()).saveOrder(any(Order.class)); // Verifica que el mètode no s'ha cridat mai }
Conclusió
La verificació d'interaccions és una part essencial de les proves amb mocks. Ens permet assegurar-nos que els nostres mocks es comporten com esperem i que els mètodes s'han cridat amb els arguments correctes. Amb les funcions de verificació de Mockito, podem escriure proves més robustes i fiables.
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