ASP.NET MVC est une plateforme qui a été introduite par Microsoft essentiellement pour augmenter la testabilité des applications Web. En ASP.NET traditionnel, il est relativement complexe de tester unitairement la logique à l’intérieur des contrôles.
- Toute la logique est séparée individuellement dans chacun des contrôles (fichiers .ascx et .aspx).
- Cette logique est contenue dans des méthodes appelées à l’intérieur du cycle de chargement des pages (page lifecycle) prédéfini par la technologie ASP.NET WebForms qui est difficile à simuler en dehors d’un contexte Web.
Le cycle évènementiel étant difficile à simuler, il devient nécessaire d’utiliser des ‘fakes’ ou ‘stubs’ des classes partielles des contrôles individuels, ce qui génère beaucoup de code pour de simples tests unitaires. De plus, la nécessité de ces ‘stubs’ complexifie passablement la pratique du développement piloté par les tests (TDD). En ASP.NET MVC, c’est la séparation en trois responsabilités distinctes (modèle, vue et contrôleur) qui augmente significativement la testabilité des systèmes développés en MVC comparativement à la plateforme populaire ASP.NET WebForms. Ainsi, toute la logique nécessaire à l’exécution des actions appelées par un groupe de vues se trouve à l’intérieur d’un seul contrôleur. Il devient donc relativement simple de tester unitairement, directement (sans ‘stub’ de contrôle) et avec un minimum de code la logique métier des actions exécutables pour un contrôleur donné. On peut ainsi plus facilement piloter le développement du comportement de nos actions en le réfléchissant à l’intérieur d’un test avant même d’en écrire le code! On peut même aller jusqu’à tester les messages d’erreur qui peuvent être retournés aux vues selon les différentes actions. Bien sûr, il est toujours nécessaire de créer des ‘fakes’ pour les objets du domaine dont la logique interne est testée dans d’autres tests unitaires. En plus d’être un moyen d’assurer la qualité du logiciel, les tests unitaires sont aussi une excellente source de documentation du code. Il est donc intéressant d’utiliser une syntaxe permettant à n’importe quel utilisateur ou programmeur qui ne connaît pas encore le système de comprendre le comportement du système. Voici une proposition pour nommer les tests et les classes de tests afin d’augmenter leur lisibilité :
- Le nom de la classe de test contient l’action : When <the controller action>,
- La méthode de test explique le comportement souhaité : <object/user> <should be> <an action>…
Un exemple de code avec MS Test :
[TestClass] public class WhenClosingTheBlog { [TestMethod] public void UserShouldSeeAWarningMessageIfHeHasNotSavedHisBlog() { var blogController = BlogControllerFactory.Generate(); var actionResult = blogController.Save(new Blog()) as RedirectToRouteResult; Assert.AreEqual(BlogController.PENDING_CHANGE_HAS_NOT_BEEN_SAVED , blogController.TempData["WarningMessage"] as string); Assert.AreEqual("Warning", actionResult.RouteValues["action"]); Assert.AreEqual("Blog", actionResult.RouteValues["controller"]); } } public class BlogController : Controller { private public const string PENDING_CHANGE_HAS_NOT_BEEN_SAVED = "Vous avez actuellement des changements non sauvegardé. Êtes vous sur de vouloir quitter la page ?"; //... [HttpPost] public ActionResult Save(Blog currentBlog) { var path = userProfile.Path; if (currentBlog.HasPendingChange) { TempData["WarningMessage"] = PENDING_CHANGE_HAS_NOT_BEEN_SAVED; return View("Warning"); } return RedirectToAction("Home"); } //... }
Cette testabilité est un aspect important qui peut justifier l’utilisation d’ASP.NET MVC dans un contexte de développement d’un projet Web nécessitant l’utilisation de pratiques d’ingénierie Agiles.