En aquest tema, aprendrem sobre les tècniques de mocking i stubbing en Groovy, que són essencials per a la realització de proves unitàries eficients i efectives. Aquestes tècniques ens permeten simular el comportament de components dependents per tal de provar el nostre codi de manera aïllada.
Què és Mocking?
Mocking és una tècnica utilitzada en les proves unitàries per crear objectes simulats que imiten el comportament dels objectes reals. Aquests objectes simulats, anomenats mocks, ens permeten definir el comportament esperat i verificar les interaccions amb altres components.
Avantatges del Mocking
- Aïllament: Permet provar una unitat de codi sense dependre d'altres components.
- Control: Ens permet definir el comportament dels mocks per a diferents escenaris.
- Verificació: Podem verificar que les interaccions amb els mocks es realitzen correctament.
Què és Stubbing?
Stubbing és una tècnica similar al mocking, però se centra en proporcionar respostes predefinides a les crides de mètodes. Els stubs són objectes simulats que retornen valors específics quan es criden els seus mètodes.
Avantatges del Stubbing
- Simplicitat: Permet definir respostes senzilles per a les crides de mètodes.
- Determinisme: Ens assegura que les proves són deterministes, ja que les respostes són predefinides.
Eines de Mocking i Stubbing en Groovy
Groovy ofereix diverses eines per a mocking i stubbing, sent les més populars:
- Mockito: Una llibreria de mocking per a Java que també es pot utilitzar en Groovy.
- Spock: Un framework de proves per a Groovy que inclou suport integrat per a mocking i stubbing.
Exemple amb Mockito
A continuació, veurem un exemple de com utilitzar Mockito per crear mocks i stubs en Groovy.
// Importem les classes necessàries import static org.mockito.Mockito.* import org.junit.Test class UserServiceTest { @Test void testGetUser() { // Creem un mock de la classe UserRepository UserRepository mockRepository = mock(UserRepository.class) // Definim el comportament del mock (stubbing) when(mockRepository.findUserById(1)).thenReturn(new User(id: 1, name: "John Doe")) // Creem una instància de la classe que volem provar UserService userService = new UserService(userRepository: mockRepository) // Cridem el mètode que volem provar User user = userService.getUser(1) // Verifiquem el resultat assert user.name == "John Doe" // Verifiquem que el mètode findUserById es va cridar una vegada amb el paràmetre 1 verify(mockRepository, times(1)).findUserById(1) } }
Exemple amb Spock
A continuació, veurem un exemple de com utilitzar Spock per crear mocks i stubs en Groovy.
import spock.lang.Specification class UserServiceSpec extends Specification { def "test getUser"() { given: // Creem un mock de la classe UserRepository UserRepository mockRepository = Mock(UserRepository) // Definim el comportament del mock (stubbing) mockRepository.findUserById(1) >> new User(id: 1, name: "John Doe") // Creem una instància de la classe que volem provar UserService userService = new UserService(userRepository: mockRepository) when: // Cridem el mètode que volem provar User user = userService.getUser(1) then: // Verifiquem el resultat user.name == "John Doe" // Verifiquem que el mètode findUserById es va cridar una vegada amb el paràmetre 1 1 * mockRepository.findUserById(1) } }
Exercicis Pràctics
Exercici 1: Mocking amb Mockito
- Crea una classe
OrderService
amb un mètodeplaceOrder
que depengui d'una classePaymentService
. - Utilitza Mockito per crear un mock de
PaymentService
i defineix el comportament del mètodeprocessPayment
. - Prova el mètode
placeOrder
deOrderService
utilitzant el mock dePaymentService
.
Solució
class PaymentService { boolean processPayment(double amount) { // Implementació real } } class OrderService { PaymentService paymentService boolean placeOrder(double amount) { return paymentService.processPayment(amount) } } import static org.mockito.Mockito.* import org.junit.Test class OrderServiceTest { @Test void testPlaceOrder() { // Creem un mock de la classe PaymentService PaymentService mockPaymentService = mock(PaymentService.class) // Definim el comportament del mock (stubbing) when(mockPaymentService.processPayment(100.0)).thenReturn(true) // Creem una instància de la classe que volem provar OrderService orderService = new OrderService(paymentService: mockPaymentService) // Cridem el mètode que volem provar boolean result = orderService.placeOrder(100.0) // Verifiquem el resultat assert result == true // Verifiquem que el mètode processPayment es va cridar una vegada amb el paràmetre 100.0 verify(mockPaymentService, times(1)).processPayment(100.0) } }
Exercici 2: Mocking amb Spock
- Crea una classe
InventoryService
amb un mètodecheckStock
que depengui d'una classeWarehouse
. - Utilitza Spock per crear un mock de
Warehouse
i defineix el comportament del mètodegetStock
. - Prova el mètode
checkStock
deInventoryService
utilitzant el mock deWarehouse
.
Solució
class Warehouse { int getStock(String item) { // Implementació real } } class InventoryService { Warehouse warehouse boolean checkStock(String item, int requiredQuantity) { return warehouse.getStock(item) >= requiredQuantity } } import spock.lang.Specification class InventoryServiceSpec extends Specification { def "test checkStock"() { given: // Creem un mock de la classe Warehouse Warehouse mockWarehouse = Mock(Warehouse) // Definim el comportament del mock (stubbing) mockWarehouse.getStock("item1") >> 10 // Creem una instància de la classe que volem provar InventoryService inventoryService = new InventoryService(warehouse: mockWarehouse) when: // Cridem el mètode que volem provar boolean result = inventoryService.checkStock("item1", 5) then: // Verifiquem el resultat result == true // Verifiquem que el mètode getStock es va cridar una vegada amb el paràmetre "item1" 1 * mockWarehouse.getStock("item1") } }
Conclusió
En aquest tema, hem après sobre les tècniques de mocking i stubbing en Groovy, així com les eines disponibles per implementar-les. Hem vist exemples pràctics utilitzant Mockito i Spock, i hem realitzat exercicis per reforçar els conceptes apresos. Aquestes tècniques són essencials per a la realització de proves unitàries efectives, ja que ens permeten aïllar el codi que volem provar i controlar el comportament dels components dependents.
Curs de Programació Groovy
Mòdul 1: Introducció a Groovy
Mòdul 2: Sintaxi i Característiques del Llenguatge Groovy
Mòdul 3: Programació Orientada a Objectes en Groovy
Mòdul 4: Característiques Avançades de Groovy
Mòdul 5: Groovy en la Pràctica
- Entrada/Sortida de Fitxers
- Treballant amb XML i JSON
- Accés a Bases de Dades
- Desenvolupament Web amb Groovy
Mòdul 6: Proves i Depuració
Mòdul 7: Ecosistema i Eines de Groovy
- Eina de Construcció Gradle
- Framework de Proves Spock
- Framework Grails
- Altres Llibreries i Eines de Groovy
Mòdul 8: Millors Pràctiques i Temes Avançats
- Estil de Codi i Convencions
- Optimització del Rendiment
- Consideracions de Seguretat
- Concurrència en Groovy