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

  1. Crea una classe OrderService amb un mètode placeOrder que depengui d'una classe PaymentService.
  2. Utilitza Mockito per crear un mock de PaymentService i defineix el comportament del mètode processPayment.
  3. Prova el mètode placeOrder de OrderService utilitzant el mock de PaymentService.

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

  1. Crea una classe InventoryService amb un mètode checkStock que depengui d'una classe Warehouse.
  2. Utilitza Spock per crear un mock de Warehouse i defineix el comportament del mètode getStock.
  3. Prova el mètode checkStock de InventoryService utilitzant el mock de Warehouse.

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.

© Copyright 2024. Tots els drets reservats