Exercice : Effectuer un test unitaire dans une fonction Azure
Les tests unitaires constituent un élément fondamental d’une méthodologie Agile. Visual Studio fournit le modèle de projet Test. Utilisez ce modèle pour créer les tests unitaires pour vos applications et vous pouvez appliquer la même technique pour tester des fonctions Azure.
Dans le scénario du site web en ligne de montres de luxe, la stratégie de votre équipe de développement est de couvrir au moins 80 % du code dans les tests unitaires. Vous souhaitez implémenter la même stratégie pour les fonctions Azure.
Ici, vous allez voir comment utiliser le framework de test xUnit
avec Visual Studio pour tester des fonctions Azure.
Créer un projet de test unitaire
La première étape consiste à créer un projet qui contient vos tests unitaires, puis à l’ajouter à la solution contenant votre application de fonction Azure. Utilisez les étapes suivantes pour créer un projet de test unitaire afin de tester la fonction WatchInfo.
Dans Visual Studio, dans la fenêtre Explorateur de solutions, cliquez avec le bouton de droite sur la solution WatchPortalFunction, sélectionnez Ajouter, puis Nouveau projet.
Dans la fenêtre Ajouter un nouveau projet, faites défiler la page vers le bas, sélectionnez l’icône du modèle Projet de test xUnit C#+, puis sélectionnez Suivant.
La fenêtre Configurer votre nouveau projet s’affiche. Dans le champ Nom du projet, entrez WatchFunctionsTests. À côté du champ Emplacement, sélectionnez l’icône de navigation, puis sélectionnez le dossier WatchPortalFunction.
Sélectionnez Suivant. La fenêtre Informations supplémentaires s’affiche.
Sous Framework cible. acceptez la valeur par défaut .NET 6.0 (support à long terme).
Sélectionnez Créer.
Une fois le projet ajouté, cliquez avec le bouton droit sur le projet WatchFunctionTests dans la fenêtre Explorateur de solutions, puis sélectionnez Gérer les packages NuGet.
Dans la fenêtre NuGet : WatchFunctionTests, sélectionnez l’onglet Parcourir. Dans la boîte Rechercher, tapez Microsoft.AspNetCore.Mvc. Sélectionnez le package Microsoft.AspNetCore.Mvc, puis Installer.
Notes
Le projet de test crée un environnement HTTP fictif. Les classes nécessaires pour effectuer cette opération se trouvent dans le package Microsoft.AspNetCore.Mvc.
Attendez que le package soit installé. Si la boîte de message Aperçu des modifications s’affiche, sélectionnez OK. Dans la boîte de message Acceptation de la licence, sélectionnez J’accepte.
Une fois le package ajouté, dans la fenêtre Explorateur de solutions, sous le projet WatchFunctionsTests, cliquez avec le bouton droit sur le fichier UnitTest1.cs, puis sélectionnez Renommer. Renommez le fichier WatchFunctionUnitTests.cs. Dans la boîte de message qui s’affiche, pour renommer toutes les références de UnitTest1 en WatchFunctionUnitTests, sélectionnez Oui.
Dans la fenêtre de l’Explorateur de solutions, sous le projet WatchFunctionsTests, cliquez avec le bouton droit sur Dépendances, puis sélectionnez Ajouter une référence de projet.
Dans la fenêtre Gestionnaire de références fenêtre, sélectionnez le projet WatchPortalFunction, puis sélectionnez OK.
Ajouter des tests unitaires pour la fonction WatchInfo
Vous pouvez maintenant ajouter des tests unitaires au projet de test. Dans le scénario des montres de luxe, vous souhaitez vérifier que la fonction WatchInfo retourne toujours une réponse OK quand un modèle est fourni dans la chaîne de requête d’une demande, et une réponse Bad si la chaîne de requête est vide ou qu’elle ne contient pas le paramètre model
.
Pour vérifier ce comportement, vous ajoutez une paire de tests Fact à WatchFunctionsTests.
Dans la fenêtre de l’Explorateur de solutions, pour afficher WatchPortalFunction dans la fenêtre de code, double-cliquez sur le fichier WatchFunctionUnitTests.cs.
En haut du fichier, ajoutez les directives
using
suivantes à la liste.using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Internal; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Logging.Abstractions;
Remplacez le nom de la méthode Test1 par TestWatchFunctionSuccess.
Dans le corps de la méthode TestWatchFunctionSuccess, ajoutez le code suivant. Cette instruction crée un contexte HTTP fictif et une demande HTTP. La demande inclut une chaîne de requête contenant le paramètre
model
défini avec la valeurabc
.var queryStringValue = "abc"; var request = new DefaultHttpRequest(new DefaultHttpContext()) { Query = new QueryCollection ( new System.Collections.Generic.Dictionary<string, StringValues>() { { "model", queryStringValue } } ) };
Ajoutez les instructions suivantes à la méthode. Cette instruction crée un enregistreur d’événements factice.
var logger = NullLoggerFactory.Instance.CreateLogger("Null Logger");
Ajoutez le code suivant à la méthode. Ces instructions appellent la fonction WatchInfo et passent la demande et l’enregistreur d’événements factices en tant que paramètres.
var response = WatchPortalFunction.WatchInfo.Run(request, logger); response.Wait();
Ajoutez le code suivant à la méthode. Ce code vérifie que la réponse de la fonction est correcte. Dans ce cas, la fonction doit retourner une réponse OK, qui contient les données attendues dans le corps.
// Check that the response is an "OK" response Assert.IsAssignableFrom<OkObjectResult>(response.Result); // Check that the contents of the response are the expected contents var result = (OkObjectResult)response.Result; dynamic watchinfo = new { Manufacturer = "abc", CaseType = "Solid", Bezel = "Titanium", Dial = "Roman", CaseFinish = "Silver", Jewels = 15 }; string watchInfo = $"Watch Details: {watchinfo.Manufacturer}, {watchinfo.CaseType}, {watchinfo.Bezel}, {watchinfo.Dial}, {watchinfo.CaseFinish}, {watchinfo.Jewels}"; Assert.Equal(watchInfo, result.Value);
La méthode complète doit ressembler à ce qui suit.
[Fact] public void TestWatchFunctionSuccess() { var queryStringValue = "abc"; var request = new DefaultHttpRequest(new DefaultHttpContext()) { Query = new QueryCollection ( new System.Collections.Generic.Dictionary<string, StringValues>() { { "model", queryStringValue } } ) }; var logger = NullLoggerFactory.Instance.CreateLogger("Null Logger"); var response = WatchPortalFunction.WatchInfo.Run(request, logger); response.Wait(); // Check that the response is an "OK" response Assert.IsAssignableFrom<OkObjectResult>(response.Result); // Check that the contents of the response are the expected contents var result = (OkObjectResult)response.Result; dynamic watchinfo = new { Manufacturer = "abc", CaseType = "Solid", Bezel = "Titanium", Dial = "Roman", CaseFinish = "Silver", Jewels = 15 }; string watchInfo = $"Watch Details: {watchinfo.Manufacturer}, {watchinfo.CaseType}, {watchinfo.Bezel}, {watchinfo.Dial}, {watchinfo.CaseFinish}, {watchinfo.Jewels}"; Assert.Equal(watchInfo, result.Value); }
Ajoutez deux autres méthodes nommées TestWatchFunctionFailureNoQueryString et TestWatchFunctionFailureNoModel. TestWatchFunctionFailureNoQueryString vérifie que la fonction WatchInfo échoue normalement si aucune chaîne de requête ne lui est donnée. TestWatchFunctionFailureNoModel vérifie le même échec si une chaîne de requête ne contenant pas de paramètre de modèle est passée à la fonction.
[Fact] public void TestWatchFunctionFailureNoQueryString() { var request = new DefaultHttpRequest(new DefaultHttpContext()); var logger = NullLoggerFactory.Instance.CreateLogger("Null Logger"); var response = WatchPortalFunction.WatchInfo.Run(request, logger); response.Wait(); // Check that the response is an "Bad" response Assert.IsAssignableFrom<BadRequestObjectResult>(response.Result); // Check that the contents of the response are the expected contents var result = (BadRequestObjectResult)response.Result; Assert.Equal("Please provide a watch model in the query string", result.Value); } [Fact] public void TestWatchFunctionFailureNoModel() { var queryStringValue = "abc"; var request = new DefaultHttpRequest(new DefaultHttpContext()) { Query = new QueryCollection ( new System.Collections.Generic.Dictionary<string, StringValues>() { { "not-model", queryStringValue } } ) }; var logger = NullLoggerFactory.Instance.CreateLogger("Null Logger"); var response = WatchPortalFunction.WatchInfo.Run(request, logger); response.Wait(); // Check that the response is an "Bad" response Assert.IsAssignableFrom<BadRequestObjectResult>(response.Result); // Check that the contents of the response are the expected contents var result = (BadRequestObjectResult)response.Result; Assert.Equal("Please provide a watch model in the query string", result.Value); }
Exécuter les tests
Dans la barre de menus supérieure, sous Tester, sélectionnez Exécuter tous les tests.
Dans la fenêtre Explorateur de tests, les trois tests doivent aboutir.
Dans la fenêtre Explorateur de solutions, sous le projet WatchPortalFunction, double-cliquez sur WatchInfo.cs pour afficher le fichier dans l’éditeur de code.
Recherchez le code suivant.
// Retrieve the model id from the query string string model = req.Query["model"];
Changez l’instruction qui définit la variable
model
comme ceci. Cette modification simule une erreur commise par le développeur dans le code.string model = req.Query["modelll"];
Dans la barre de menus supérieure, sous Tester, sélectionnez Exécuter tous les tests. Cette fois-ci, le test TestWatchFunctionSuccess doit échouer. Cet échec se produit parce que la fonction WatchInfo n’a pas trouvé le paramètre nommé
modelll
dans la chaîne de requête : la fonction retourne donc une réponse Bad (Incorrect).
Dans cette unité, vous avez vu comment créer un projet de test unitaire et comment implémenter des tests unitaires pour une fonction Azure.