Introduction : pourquoi sans mocks et fixtures les tests sont une loterie
\n\nImaginez que vous écrivez du code pour un vaisseau spatial. Votre fonction calcule une trajectoire en accédant au module de contrôle du moteur. Comment vérifier que la trajectoire est correcte sans lancer le vrai moteur ? Dans le monde réel, c'est une catastrophe. Dans le monde du C++, c'est une tâche pour les mock-objets et les fixtures.
\n\nSi vous avez déjà écrit des tests unitaires en C++, vous avez sûrement rencontré des problèmes : le test échoue à cause du réseau, de la base de données ou du système de fichiers. Ou vous passez 10 lignes à préparer les données pour chaque vérification. Cela vous dit quelque chose ? Alors cet article est pour vous.
\n\nNous allons voir comment les mock-objets en C++ aident à isoler le code du monde extérieur, et comment les fixtures permettent de réutiliser la configuration des tests. Pas de blabla, seulement du code et de la pratique. C'est parti !
\n\nQue sont les mock-objets et pourquoi en a-t-on besoin en C++
\n\nUn mock-objet (ou simplement mock) est un remplacement d'un objet réel qui imite son comportement. Vous dites au mock : « Quand la méthode getData() est appelée, retourne 42 ». Et il retourne docilement 42, sans accéder à la base de données, à l'API ou au fichier.
\n\nEn C++, les mocks sont particulièrement importants car le langage ne pardonne pas les erreurs. Si votre classe dépend du réseau et que le réseau tombe, le test échouera, même si votre code est parfait. Les mocks résolvent ce problème : ils isolent le code testé.
\n\nLes principaux scénarios d'utilisation des mock-objets en C++ :
\n- \n
- Services externes (bases de données, API REST, fichiers). \n
- Calculs complexes qui ralentissent les tests (cryptographie, rendu). \n
- Fonctions non déterministes (rand(), time()). \n
- Vérification des interactions : la méthode a-t-elle été appelée, combien de fois, avec quels arguments. \n
Pour créer des mocks en C++, la bibliothèque de facto standard est Google Mock (également appelée gmock), qui est fournie avec Google Test. Mais on peut aussi écrire des mocks manuellement — pour les petits projets, c'est même plus simple.
\n\nFixtures : préparer la scène pour le test
\n\nUne fixture (test fixture) est un ensemble d'objets et de données nécessaires à l'exécution du test. Au lieu d'écrire à chaque fois :
\n\nMyClass obj;\nobj.init("data");\nobj.connect();\n\n…vous placez cela dans une fixture. Google Test prend en charge les fixtures via l'héritage de ::testing::Test. Ce n'est pas seulement pratique — c'est une bonne pratique de test en C++.
Les fixtures résolvent trois problèmes :
\n- \n
- Réutilisation du code — configurez une fois, utilisez dans tous les tests. \n
- Propreté des tests — chaque test commence dans le même état. \n
- Nettoyage automatique — si des ressources doivent être libérées, cela se fait dans le destructeur de la fixture. \n
Et maintenant, combinons les mocks et les fixtures dans un exemple concret.
\n\nÉcrire un test avec un mock-objet et une fixture : exemple réel
\n\nSupposons que nous ayons une classe WeatherReporter qui reçoit des données météo via une API. Nous voulons tester la méthode getTemperature() sans accéder au vrai serveur.
Étape 1. Définir l'interface
\n\nPour pouvoir substituer un mock, nous avons besoin d'une classe abstraite. C'est un point clé : les mocks fonctionnent via le polymorphisme.
\n\n// weather_api.h\nclass WeatherAPI {\npublic:\n virtual ~WeatherAPI() = default;\n virtual double getTemperature(const std::string& city) = 0;\n virtual bool isAvailable() = 0;\n};\n\nÉtape 2. Implémenter le mock avec Google Mock
\n\n// mock_weather_api.h\n#include <gmock/gmock.h>\n#include "weather_api.h"\n\nclass MockWeatherAPI : public WeatherAPI {\npublic:\n MOCK_METHOD(double, getTemperature, (const std::string& city), (override));\n MOCK_METHOD(bool, isAvailable, (), (override