共用方式為


使用 Visual Studio Code 從 Azure Logic Apps 中的標準工作流程定義建立單元測試

適用於:Azure Logic Apps (標準)

單元測試是讓您的應用程式或解決方案在整個軟體開發生命週期中保持可靠且精確的基本做法。 單元測試可協助您有效率且有系統地驗證解決方案中的關鍵元件。

針對標準邏輯應用程式工作流程,您可以使用 Visual Studio Code 和 Azure Logic Apps (Standard) 擴充功能來建立單元測試。 這項功能可讓您使用工作流程定義來建立單元測試,並針對邏輯應用程式解決方案支援的案例量身打造,而不需要連線到任何外部服務、系統或 API。 此方法可讓您測試工作流程,而不需要與外部服務、系統或 API 互動,並提供下列優點:

  • 在部署至其他環境之前,先識別並解決潛在問題,以改善工作流程品質。

  • 簡化與開發程式的單元測試整合,同時確保一致且精確的工作流程行為。

本指南說明如何從工作流程建立單元測試定義。 此定義會模擬來自每個工作流程作業的外部呼叫,而不需要變更工作流程邏輯。 當您建立工作流程的單元測試時,您會取得包含下列資料夾的單元測試專案:

  • 包含針對工作流程中每個可模擬作業的強型別類別的資料夾。

  • 為每個單元測試定義創建的資料夾。 此資料夾包含包含範例類別和方法的 C# 檔案。 您可以使用這個類別和方法來設定自己的判斷提示、確認工作流程如預期般運作,並確定工作流程在較大的 Azure 生態系統中可可靠且可預測地運作。

先決條件

限制和已知問題

  • 此版本目前僅支援 C# 來建立單元測試。

  • 此版本不支援非模擬的動作。 請確定已模擬工作流程執行路徑中的所有動作。

  • 此版本不支援下列動作類型:

    • 整合帳戶動作
    • EDI 編碼和譯碼動作

複習基本概念

下列清單包含標準工作流程單元測試的基本但重要概念:

  • 邏輯應用程式單元測試

    插入模擬物件的受控工作流程執行。 這些物件代表工作流程觸發程式或依賴於外部服務或系統的動作。

  • 可仿真動作

    相依於外部服務或系統的工作流程動作。 您可以將這些動作轉換成仿真的動作,以進行單元測試建立和執行。

從工作流程定義建立單元測試

  1. 在 Visual Studio Code 中,開啟您的標準邏輯應用程式專案。

  2. 在您的專案中,展開工作流程定義資料夾。

  3. workflow.json 檔案的快捷方式功能表中,選取 [ 開啟設計工具]。

  4. 在設計工具工具列上,選取 [建立單元測試]。

    此螢幕快照顯示 Visual Studio Code、Standard 邏輯應用程式專案、工作流程設計工具,以及用來建立單元測試的已選取命令。

  5. 提供用於單元測試、單元測試類別和 C# 檔案的名稱。

    名為 [測試 ] 的新資料夾現在會出現在您的專案工作區中。 此資料夾具有下列結構:

    此螢幕快照顯示 Visual Studio Code、Standard 邏輯應用程式專案,以及具有單元測試資料夾和檔案的 [測試] 資料夾。

    資料夾或檔案 說明
    Tests
    || <logic-app-name>
    Tests 資料夾中,當您將單元測試新增至邏輯應用程式專案時,會出現一個 <logic-app-name> 資料夾。
    Tests
    || <logic-app-name>
    ||| <workflow-name>
    <logic-app-name> 資料夾中,當您新增工作流程的單元測試時,會出現一個 <workflow-name> 資料夾。
    Tests
    || <logic-app-name>
    ||| <workflow-name>
    |||| MockOutputs
    ||||| <operation-name-outputs>cs
    <workflow-name> 資料夾中,MockOutputs 資料夾包含 C#(.cs)檔案,其中包含工作流程中每個連接器作業的強類型類別。 每個 .cs 檔案名都會使用下列格式:

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

    如果連接器作業具有 動態合約,那麼每一個 動態類型都會對應一個類別。 動態類型是指根據為該參數提供的值,具有不同輸入和輸出的作業參數。 您可以使用這些類別來擴充單元測試,並從頭開始建立新的模擬。
    Tests
    || <logic-app-name>
    ||| <workflow-name>
    |||| <unit-test-name>
    ||||| <unit-test-name>.cs
    <workflow-name> 資料夾中, <unit-test-name> 資料夾包含檔案 <unit-test-name>.cs 。 您可以使用這個檔案,其中包含範例 C# 類別和方法,以執行和判斷提示結果。 您可以編輯此檔案,以符合您的特定測試案例。

檢閱單元測試 *.cs 檔案

此單元測試類別提供一個架構,可藉由模擬觸發程式和動作來測試標準邏輯應用程式工作流程。 此類別可讓您測試工作流程,而不需要實際呼叫外部服務或 API。

測試類別結構

典型的單元測試類別會使用下列結構:

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

Setup() 方法

這個方法會使用測試設定組態檔的路徑來具現化 TestExecutor 類別。 方法會在每次測試執行之前執行,並建立 的新實例 TestExecutor

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

範例測試方法

下一節說明您可以在單元測試類別中使用的範例測試方法。

靜態模擬數據測試

下列方法示範如何使用靜態模擬數據來測試您的工作流程。 在此方法中,您可以完成下列工作:

  • 在您的模擬動作上設定屬性值。
  • 使用已設定的模擬數據執行工作流程。
  • 確認執行成功。
[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);
}

動態模擬數據測試

下列方法示範如何搭配回呼方法使用動態模擬數據。 此方法提供兩個選項,可動態產生模擬數據:

這兩種方法都可讓您根據單元測試執行內容建立動態回應。

[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);
}

協助程式方法

下一節說明範例測試方法所使用的方法。 協助程式方法會出現在類別定義中的測試方法底下。

回撥方法

下列方法會動態產生模擬數據。 方法名稱會根據靜態或動態模擬數據測試方法中的模擬動作名稱而有所不同。 您可以編輯此方法,根據測試案例需求傳回不同的模擬回應,或使用它作為範本來建立您自己的動態回呼方法。

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()

        }
    );
}