Tests en Java : unit, integration, e2e de A à Z

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course
```html

Introduction : Pourquoi les tests sont le fondement d'un code Java de qualité

Chaque développeur Java a déjà été confronté à une situation où, après avoir corrigé un bug, trois nouveaux apparaissaient. Pour briser ce cercle vicieux, il existe les tests. Ce n'est pas simplement une case à cocher dans une liste, mais une discipline professionnelle qui préserve les nerfs, l'argent et la réputation du produit.

Dans cet article, nous allons décomposer les trois niveaux clés de test : unit (tests unitaires), integration (tests d'intégration) et e2e (tests de bout en bout). Nous les examinerons à travers des exemples pratiques en Java, en utilisant des frameworks populaires : JUnit 5, Mockito, Spring Boot Test et Selenium. Vous apprendrez à construire une pyramide de tests correcte et à ne pas surcharger votre projet avec des tests inutiles.

1. Tests unitaires : Vérification des unités atomiques de code

Les tests unitaires sont le niveau le plus bas et le plus rapide. Ils vérifient le fonctionnement d'une seule « unité » (généralement une méthode ou une classe) en isolation des dépendances externes (BDD, API, système de fichiers).

1.1 Outils et frameworks

  • JUnit 5 — le standard de facto pour écrire des tests en Java.
  • Mockito — une bibliothèque pour créer des bouchons (mocks) et des stubs.
  • AssertJ — une bibliothèque pour des assertions fluides.

1.2 Exemple de test unitaire avec JUnit 5 et Mockito

Imaginons que nous ayons un service OrderService qui dépend d'un repository PaymentRepository. Nous voulons tester la logique du service sans appeler la vraie base de données.

// Classe à tester
public class OrderService {
    private final PaymentRepository paymentRepository;

    public OrderService(PaymentRepository paymentRepository) {
        this.paymentRepository = paymentRepository;
    }

    public String processOrder(Order order) {
        if (order.getAmount() <= 0) {
            throw new IllegalArgumentException("Le montant de la commande doit être positif");
        }
        boolean success = paymentRepository.pay(order);
        return success ? "Paiement réussi" : "Erreur de paiement";
    }
}

// Test unitaire
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
class OrderServiceTest {

    @Mock
    private PaymentRepository paymentRepository;

    @InjectMocks
    private OrderService orderService;

    @Test
    void testProcessOrder_Success() {
        // Arrange
        Order order = new Order(100.0);
        when(paymentRepository.pay(order)).thenReturn(true);

        // Act
        String result = orderService.processOrder(order);

        // Assert
        assertEquals("Paiement réussi", result);
        verify(paymentRepository, times(1)).pay(order);
    }

    @Test
    void testProcessOrder_NegativeAmount() {
        // Arrange
        Order order = new Order(-10.0);

        // Act & Assert
        assertThrows(IllegalArgumentException.class, () -> {
            orderService.processOrder(order);
        });
    }
}

Bonnes pratiques pour les tests unitaires :

  • Un test = une vérification (principe FIRST : Fast, Isolated, Repeatable, Self-validating, Timely).
  • Utilisez des noms explicites : shouldReturnSuccess_whenPaymentIsApproved.
  • Ne testez pas les méthodes privées — testez le contrat public.
  • Couvrez les cas limites : null, chaînes vides, nombres négatifs.

2. Tests d'intégration : Vérification de l'interaction des composants

Les tests d'intégration vérifient comment différents modules du système

```

Blogs

Book Recommendations