[Teched 2007] Manual and Dynamic Mocks wit C# and Visual Studio Team System
Mark Seemann - Senior Consultat Microsoft Services
Une session consacrée à la création de Mocks, une des techniques avancées de tests unitaires, avec pour les exemples comme utilisation de Framework de test unitaire: MSTest.
Objectif de la session:
- Rappels sur l'intérêt des tests doubles
- Aide au choix de l'outil le plus adapté pour l'utilisation de Mocks
Rappel sur l'importance de la relation fonction à tester <=> dépendances: Dans un test unitaire, il est souhaitable de faire abstraction des dépendances (appels externes) de la fonction à tester. Le but d'un "test double" est de simuler / remplacer une dépendance pour pouvoir cibler uniquement l'unité testée.
Un rappel a aussi été fait sur l'importance de la clarté et de la simplicité des tests unitaires car ceux-ci peuvent servir de documentation pour une API en expliquant par l'exemple le fonctionnement de chaque méthode de celle-ci.
Concernant les tests doubles, il en existe plusieurs types:
• Dummies, fakes: remplacement d'un objet utilisé dans la méthode à tester par un objet qui ne sera jamais utilisé: juste pour permettre à la méthode de compiler et de s'exécuter
• Fakes: Remplace une fonctionnalité d'une dépendance par une implémentation différente
• Spies: permet de vérifier les appels fait a un composant externe en se mettant a sa place et en registrant ceux-ci
• Stubs: objet utilisé pour remplacer un composant réél et simuler les interactions avec celui-ci
• Mocks: Remplace un objet utilisé par le code a tester en simulant un comportement identique
• re-implémentation d'une dépendance complète avec éventuellement simplification
Pour la création de Mocks, il existe deux approches: soit une implémentation complète (manual mock), soit l'utilisation d'un Framework pour le générer automatiquement a l'exécution de l'application (dynamick mock).
Exemple de Dynamick Mock Librairies téléchargeables gratuitement sur internet
- Rhino Mocks: système d'enregistrement, type safe
- NMOck2: string-based.
Exemple d'implémentation avec NMock2:
Mockery mocks = new Mockery();
//création d'un mock pour remplacer l'objet d'accès aux données "IShopDataAccess"
IShopDataAccess dataAccess = mocks.NewMock<IShopDataAccess>();
//spécification du comportement attendu: Dans l'objet DataAccess la méthode "GetProductPrive" appelée avec l'argument "1234" doit renvoyer "10f".
Expect.Once.On(dataAccess).Method("GetProductPrive").with(1234).Will(Return.Value(10f));
//Appel de l'objet a tester avec le Mock en paramètre
Order o = new Order(dataAccess);
o.Lines.Add(1234).Quantity = 4;
decimal total = o.CalculateTotal();
//on vérifie que le Mock a bien été appelé comme attendu
mocks.VerifyAllExpectationsHaveBeenMet();
Pour aller plus loin:
• un article de Mark Seemann très complet sur les tests doubles dans MSN Mag: http://msdn.microsoft.com/msdnmag/issues/07/09/MockTesting/default.aspx
• Le livre xUnit test patteners: Refactoring Test code: http://www.amazon.fr/xUnit-Test-Patterns-Refactoring-Code/dp/0131495054/ref=pd_bbs_sr_1/402-5245909-8257750?ie=UTF8&s=english-books&qid=1194787748&sr=8-1