Partager via


Créer des tests unitaires à partir de définitions de flux de travail Standard dans Azure Logic Apps avec Visual Studio Code

S’applique à : Azure Logic Apps (Standard)

Le test unitaire est une pratique essentielle qui maintient votre application ou votre solution fiable et précise tout au long du cycle de vie du développement logiciel. Les tests unitaires vous aident à valider efficacement et systématiquement les composants clés de votre solution.

Pour les flux de travail d’application logique standard, vous pouvez créer des tests unitaires à l’aide de Visual Studio Code et de l’extension Azure Logic Apps (Standard). Cette fonctionnalité vous permet d’utiliser des définitions de flux de travail pour créer des tests unitaires et les adapter aux scénarios pris en charge par votre solution d’application logique, sans avoir besoin de connexions à des services, systèmes ou API externes. Cette approche vous permet de tester vos flux de travail sans avoir à interagir avec des services externes, des systèmes ou des API et offre les avantages suivants :

  • Améliorez la qualité du flux de travail en identifiant et en traitant les problèmes potentiels avant de les déployer dans d’autres environnements.

  • Simplifiez l’intégration des tests unitaires à votre processus de développement, tout en garantissant un comportement de flux de travail cohérent et précis.

Ce guide montre comment créer une définition de test unitaire à partir d’un flux de travail. Cette définition simule les appels externes de chaque opération de flux de travail sans modifier la logique du flux de travail. Lorsque vous créez un test unitaire pour un flux de travail, vous obtenez un projet de test unitaire qui inclut les dossiers suivants :

  • Un dossier qui contient des classes fortement typées pour chaque opération simulable dans votre flux de travail.

  • Dossier pour chaque définition de test unitaire. Ce dossier inclut un fichier C# qui contient un exemple de classe et de méthodes. Vous utilisez cette classe et ces méthodes pour configurer vos propres assertions, vérifiez que le flux de travail se comporte comme prévu et assurez-vous que le flux de travail se comporte de manière fiable et prévisible dans votre plus grand écosystème Azure.

Conditions préalables

Limitations et problèmes connus

  • Cette version prend actuellement en charge uniquement C# pour la création de tests unitaires.

  • Cette version ne prend pas en charge les actions non simulées. Assurez-vous que toutes les actions du chemin d’exécution du flux de travail sont simulées.

  • Cette version ne prend pas en charge les types d’actions suivants :

    • Actions du compte d'intégration
    • Actions d'encodage et de décodage EDI

Passer en revue les concepts de base

La liste suivante inclut des concepts de base mais importants sur les tests unitaires pour les flux de travail Standard :

  • Test unitaire d’application logique

    Exécution contrôlée du flux de travail qui injecte des objets fictifs. Ces objets représentent le déclencheur de flux de travail ou les actions qui dépendent de services ou de systèmes externes.

  • Action simulable

    Action de flux de travail qui dépend d’un service ou d’un système externe. Vous pouvez convertir ces actions en actions fictives pour la création et l’exécution de tests unitaires.

Créer un test unitaire à partir d’une définition de flux de travail

  1. Dans Visual Studio Code, ouvrez votre projet d’application logique Standard.

  2. Dans votre projet, développez le dossier de définition de flux de travail.

  3. Dans le menu contextuel du fichier workflow.json, sélectionnez Ouvrir le concepteur.

  4. Dans la barre d’outils du concepteur, sélectionnez Créer un test unitaire.

    Capture d’écran montrant Visual Studio Code, le projet d’application logique standard, le concepteur de flux de travail et la commande sélectionnée pour créer un test unitaire.

  5. Fournissez un nom à utiliser pour le fichier de test unitaire, de classe de test unitaire et de fichier C#.

    Un nouveau dossier nommé Tests s’affiche désormais dans votre espace de travail de projet. Ce dossier a la structure suivante :

    Capture d’écran montrant Visual Studio Code, le projet d’application logique standard et le dossier Tests avec des dossiers et des fichiers de test unitaires.

    Fichier ou dossier Descriptif
    Tests
    || <logic-app-name>
    Dans le Tests dossier, un <logic-app-name> dossier s’affiche lorsque vous ajoutez des tests unitaires à un projet d’application logique.
    Tests
    || <logic-app-name>
    ||| <workflow-name>
    Dans le <logic-app-name> dossier, un <workflow-name> dossier s’affiche lorsque vous ajoutez des tests unitaires pour un flux de travail.
    Tests
    || <logic-app-name>
    ||| <workflow-name>
    |||| MockOutputs
    < operation-name-outputs >||||| .cs
    Dans le <workflow-name> dossier, le MockOutputs dossier contient un fichier C# (.cs) avec des classes fortement typées pour chaque opération de connecteur dans le flux de travail. Chaque nom de fichier .cs utilise le format suivant :

    < operation-name >[Trigger\|Action]Output.cs

    Si une opération de connecteur a des contrats dynamiques, une classe apparaît pour chaque type dynamique. Un type dynamique fait référence à un paramètre d’opération qui a différentes entrées et sorties en fonction de la valeur fournie pour ce paramètre. Vous pouvez utiliser ces classes pour étendre vos tests unitaires et créer de nouvelles maquettes à partir de zéro.
    Tests
    || <logic-app-name>
    ||| <workflow-name>
    |||| <unit-test-name>
    ||||| <unit-test-name>.cs
    Dans le <workflow-name> dossier, le <unit-test-name> dossier contient un <unit-test-name>.cs fichier. Vous utilisez ce fichier, qui contient un exemple de classe C# et de méthodes, pour exécuter et déclarer des résultats. Vous pouvez modifier ce fichier pour qu’il corresponde à vos scénarios de test spécifiques.

Passez en revue le fichier *.cs de test unitaire

Cette classe de test unitaire fournit une infrastructure pour tester les flux logiques d'application standard en simulant des déclencheurs et des actions. Cette classe vous permet de tester les flux de travail sans appeler réellement des services externes ou des API.

Structure de classe de test

Une classe de test unitaire classique utilise la structure suivante :

[TestClass]
public class <unit-test-name>
{
    public TestExecutor TestExecutor;

    [TestInitialize]
    public void Setup()
    {
        this.TestExecutor = new TestExecutor("<workflow-name>/testSettings.config");
    }

    // Add test methods here.

    // Add helper methods here.
}

Méthode Setup()

Cette méthode instancie la TestExecutor classe à l’aide du chemin d’accès à votre fichier de configuration des paramètres de test. La méthode s’exécute avant chaque exécution de test et crée une nouvelle instance de TestExecutor.

[TestInitialize]
public void Setup()
{
    this.TestExecutor = new TestExecutor("<workflow-name>/testSettings.config");
}

Exemples de méthodes de test

La section suivante décrit les exemples de méthodes de test que vous pouvez utiliser dans votre classe de test unitaire.

Test de données fictives statiques

La méthode suivante montre comment utiliser des données fictives statiques pour tester votre flux de travail. Dans cette méthode, vous pouvez effectuer les tâches suivantes :

  • Définissez les valeurs des propriétés de vos actions simulées.
  • Exécutez le flux de travail avec les données fictives configurées.
  • Vérifiez que l’exécution a réussi.
[TestMethod]
public async Task <workflow-name>_<unit-test-name>_ExecuteWorkflow_SUCCESS_Sample1()
{
    // PREPARE mock: Generate mock trigger data.
    var triggerMockOutput = new WhenMessagesAreAvailableInAQueuePeeklockTriggerOutput();
    // Sample that shows how to set the properties for triggerMockOutput
    // triggerMockOutput.Body.Id = "SampleId";
    var triggerMock = new WhenMessagesAreAvailableInAQueuePeeklockTriggerMock(outputs: triggerMockOutput);

    // Generate mock action data.
    var actionMockOutput = new CallExternalAPIActionOutput();
    // Sample that shows how to set the properties for actionMockOutput
    // actionMockOutput.Body.Name = "SampleResource";
    // actionMockOutput.Body.Id = "SampleId";
    var actionMock = new CallExternalAPIActionMock(name: "Call_External_API", outputs: actionMockOutput);

    // ACT: Create the UnitTestExecutor instance. Run the workflow with mock data.
    var testMock = new TestMockDefinition(
        triggerMock: triggerMock,
        actionMocks: new Dictionary<string, ActionMock>()
        {
            {actionMock.Name, actionMock}
        });
    var testRun = await this.TestExecutor
        .Create()
        .RunWorkflowAsync(testMock: testMock).ConfigureAwait(continueOnCapturedContext: false);

    // ASSERT: Confirm successful workflow execution and that the status is 'Succeeded'.
    Assert.IsNotNull(value: testRun);
    Assert.AreEqual(expected: TestWorkflowStatus.Succeeded, actual: te
    stRun.Status);
}

Test dynamique des données fictives

La méthode suivante montre comment utiliser des données fictives dynamiques avec des méthodes de rappel. Cette approche vous offre deux options qui génèrent dynamiquement des données fictives :

Les deux approches vous permettent de créer des réponses dynamiques basées sur le contexte d’exécution de test unitaire.

[TestMethod]
public async Task <workflow-name>_<unit-test-name>_ExecuteWorkflow_SUCCESS_Sample2()
{
    // PREPARE: Generate mock trigger data.
    var triggerMockOutput = new WhenMessagesAreAvailableInAQueuePeeklockTriggerOutput();
    // Sample that shows how to set triggerMockOutput properties.
    // triggerMockOutput.Body.Flag = true;
    var triggerMock = new WhenMessagesAreAvailableInAQueuePeeklockTriggerMock(outputs: triggerMockOutput);

    // PREPARE: Generate mock action data.
    // OPTION 1: Define a callback class.
    var actionMock = new CallExternalAPIActionMock(name: "Call_External_API", onGetActionMock: CallExternalAPIActionMockOutputCallback);

    // OPTION 2: Define inline with a lambda function.
    /*var actionMock = new CallExternalAPIActionMock(name: "Call_External_API", onGetActionMock: (testExecutionContext) =>
    {
        return new CallExternalAPIActionMock(
            status: TestWorkflowStatus.Succeeded,
            outputs: new CallExternalAPIActionOutput {

                // If this account contains a JObject Body,
                // set the properties you want here:
                // Body = "something".ToJObject()

            }
        );
    });*/

    // ACT: Create the UnitTestExecutor instance. Run the workflow with mock data.
    var testMock = new TestMockDefinition(
        triggerMock: triggerMock,
        actionMocks: new Dictionary<string, ActionMock>()
        {
            {actionMock.Name, actionMock}
        });
    var testRun = await this.TestExecutor
        .Create()
        .RunWorkflowAsync(testMock: testMock).ConfigureAwait(continueOnCapturedContext: false);

    // ASSERT: Confirm successful workflow execution and that the status is 'Succeeded'.
    Assert.IsNotNull(value: testRun);
    Assert.AreEqual(expected: TestWorkflowStatus.Succeeded, actual: testRun.Status);
}

Méthodes d’assistance

La section suivante décrit les méthodes utilisées par les exemples de méthodes de test. Les méthodes d’assistance apparaissent sous les méthodes de test dans la définition de classe.

Méthode de rappel

La méthode suivante génère dynamiquement des données fictives. Le nom de la méthode varie en fonction du nom de l’action simulée dans les méthodes de test pour les données fictives statiques ou dynamiques. Vous pouvez modifier cette méthode pour retourner différentes réponses fictives en fonction des exigences de votre scénario de test ou l’utiliser comme modèle pour créer vos propres méthodes de rappel dynamique.

public CallExternalAPIActionMock CallExternalAPIActionMockOutputCallback(TestExecutionContext context)
{
    // Sample mock data: Dynamically change the mocked data for 'actionName'.
    return new CallExternalAPIActionMock(
        status: TestWorkflowStatus.Succeeded,
        outputs: new CallExternalAPIActionOutput {

            // If this account contains a JObject Body, 
            // set the properties you want here:
            // Body = "something".ToJObject()

        }
    );
}