Exercice : Effectuer un test unitaire dans une fonction Azure

Effectué

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.

  1. 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.

    Capture d’écran de l’Explorateur de solutions avec la commande Ajouter un nouveau projet à la solution.

  2. Dans la fenêtre Ajouter un nouveau projet, faites défiler vers le bas, sélectionnez le modèle d’icône Projet de test xUnitC#+, puis sélectionnez Suivant.

    Capture d’écran de la fenêtre Ajouter un nouveau projet. Le modèle de projet de test xUnit est sélectionné.

  3. 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.

  4. Sélectionnez Suivant. La fenêtre Informations supplémentaires s’affiche.

  5. Sous Framework cible. acceptez la valeur par défaut .NET 6.0 (support à long terme).

  6. Sélectionnez Créer.

  7. 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.

  8. 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.

    Capture d’écran de la fenêtre du Gestionnaire de package NuGet. L’utilisateur installe le package Microsoft.AspNetCore.Mvc.

    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.

  9. 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.

  10. 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.

  11. 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.

  12. 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.

  1. 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.

  2. 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;
    
  3. Remplacez le nom de la méthode Test1 par TestWatchFunctionSuccess.

  4. 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 valeur abc.

    var queryStringValue = "abc";
    var request = new DefaultHttpRequest(new DefaultHttpContext())
    {
        Query = new QueryCollection
        (
            new System.Collections.Generic.Dictionary<string, StringValues>()
            {
                { "model", queryStringValue }
            }
        )
    };
    
  5. Ajoutez les instructions suivantes à la méthode. Cette instruction crée un enregistreur d’événements factice.

    var logger = NullLoggerFactory.Instance.CreateLogger("Null Logger");
    
  6. 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();
    
  7. 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);
    }
    
  8. 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

  1. Dans la barre de menus supérieure, sous Tester, sélectionnez Exécuter tous les tests.

    Capture d’écran du menu Test dans Visual Studio. L’utilisateur a sélectionné Exécuter -> Tous les tests.

  2. Dans la fenêtre Explorateur de tests, les trois tests doivent aboutir.

    Capture d’écran de la fenêtre Team Explorer. Les trois tests ont été exécutés.

  3. 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.

  4. Recherchez le code suivant.

    // Retrieve the model id from the query string
    string model = req.Query["model"];
    
  5. 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"];
    
  6. 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).

    Capture d’écran de la fenêtre Team Explorer. Le test TestWatchFunctionSuccess a échoué.

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.