使用模擬服務整合在 Step Functions Local 中進行測試 - AWS Step Functions

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用模擬服務整合在 Step Functions Local 中進行測試

不支援 Step Functions Local

Step Functions Local 不提供功能同位,且不受支援

您可以考慮模擬 Step Functions 的第三方解決方案,用於測試目的。

在 Step Functions Local 中,您可以使用模擬服務整合來測試狀態機器的執行路徑,而無需實際呼叫整合服務。若要將狀態機器設定為使用模擬服務整合,您可以建立模擬組態檔案。在此檔案中,您會將服務整合所需的輸出定義為模擬回應,並使用模擬回應來模擬執行路徑做為測試案例的執行。

透過將模擬組態檔案提供給 Step Functions Local,您可以執行使用測試案例中所指定模擬回應的狀態機器來測試服務整合呼叫,而不是進行實際的服務整合呼叫。

注意

如果您未在模擬組態檔案中指定模擬服務整合回應,Step Functions Local 會使用您在設定 Step Functions Local 時設定的端點來叫用 AWS 服務整合。如需設定 Step Functions Local 端點的詳細資訊,請參閱 設定 Step Functions Local 的組態選項

本主題使用下列清單中定義的幾個概念:

  • 模擬服務整合 - 指設定為使用模擬回應而非執行實際服務呼叫的任務狀態。

  • 模擬回應 - 指任務狀態可設定為使用的模擬資料。

  • 測試案例 - 指設定為使用模擬服務整合的狀態機器執行。

  • 模擬組態檔案 - 指包含 的模擬組態檔案JSON,定義模擬服務整合、模擬回應和測試案例。

設定模擬服務整合

您可以使用 Step Functions Local 模擬任何服務整合。不過,Step Functions Local 不會強制模擬與實際 相同APIs。模擬任務永遠不會呼叫服務端點。如果您未指定模擬回應,任務會嘗試呼叫服務端點。此外,當您使用 模擬任務時,Step Functions Local 會自動產生任務字符.waitForTaskToken

步驟 1:在模擬組態檔案中指定模擬服務整合

您可以使用 Step Functions AWS SDK Local 測試 Step Functions 和最佳化的服務整合。下圖顯示狀態機器定義索引標籤中定義的狀態機器:

模擬服務整合範例。

若要這樣做,您必須建立包含 中定義的區段的模擬組態檔案模擬組態檔案結構

  1. 建立名為 的檔案MockConfigFile.json,以設定具有模擬服務整合的測試。

    下列範例顯示參考狀態機器的模擬組態檔案,其中有兩個已定義狀態名為 LambdaStateSQSState

    Mock configuration file example

    以下是模擬組態檔案的範例,示範如何模擬叫用 Lambda 函數傳送訊息至 Amazon SQS的回應。在此範例中,LambdaSQSIntegration狀態機器包含三個名為 HappyPath、 的測試案例RetryPathHybridPath並模擬名為 LambdaStateTask的狀態SQSState。這些狀態使用 MockedLambdaSuccessMockedSQSSuccessMockedLambdaRetry模擬服務回應。這些模擬服務回應會在 檔案的 MockedResponses區段中定義。

    { "StateMachines":{ "LambdaSQSIntegration":{ "TestCases":{ "HappyPath":{ "LambdaState":"MockedLambdaSuccess", "SQSState":"MockedSQSSuccess" }, "RetryPath":{ "LambdaState":"MockedLambdaRetry", "SQSState":"MockedSQSSuccess" }, "HybridPath":{ "LambdaState":"MockedLambdaSuccess" } } } }, "MockedResponses":{ "MockedLambdaSuccess":{ "0":{ "Return":{ "StatusCode":200, "Payload":{ "StatusCode":200, "body":"Hello from Lambda!" } } } }, "LambdaMockedResourceNotReady":{ "0":{ "Throw":{ "Error":"Lambda.ResourceNotReadyException", "Cause":"Lambda resource is not ready." } } }, "MockedSQSSuccess":{ "0":{ "Return":{ "MD5OfMessageBody":"3bcb6e8e-7h85-4375-b0bc-1a59812c6e51", "MessageId":"3bcb6e8e-8b51-4375-b0bc-1a59812c6e51" } } }, "MockedLambdaRetry":{ "0":{ "Throw":{ "Error":"Lambda.ResourceNotReadyException", "Cause":"Lambda resource is not ready." } }, "1-2":{ "Throw":{ "Error":"Lambda.TimeoutException", "Cause":"Lambda timed out." } }, "3":{ "Return":{ "StatusCode":200, "Payload":{ "StatusCode":200, "body":"Hello from Lambda!" } } } } } }
    State machine definition

    以下是名為 的狀態機器定義範例LambdaSQSIntegration,定義兩個名為 LambdaState和 的服務整合任務狀態SQSStateLambdaState包含以 為基礎的重試政策States.ALL

    { "Comment":"This state machine is called: LambdaSQSIntegration", "StartAt":"LambdaState", "States":{ "LambdaState":{ "Type":"Task", "Resource":"arn:aws:states:::lambda:invoke", "Parameters":{ "Payload.$":"$", "FunctionName":"HelloWorldFunction" }, "Retry":[ { "ErrorEquals":[ "States.ALL" ], "IntervalSeconds":2, "MaxAttempts":3, "BackoffRate":2 } ], "Next":"SQSState" }, "SQSState":{ "Type":"Task", "Resource":"arn:aws:states:::sqs:sendMessage", "Parameters":{ "QueueUrl":"https://sqs.us-east-1.amazonaws.com/123456789012/myQueue", "MessageBody.$":"$" }, "End": true } } }

    您可以使用下列其中一個測試案例,執行模擬組態檔案中參考LambdaSQSIntegration的狀態機器定義:

    • HappyPath - 此測試MockedSQSSuccess會分別模擬 LambdaStateSQSState 使用 MockedLambdaSuccess 和 的輸出。

      • LambdaState 將傳回下列值:

        "0":{ "Return":{ "StatusCode":200, "Payload":{ "StatusCode":200, "body":"Hello from Lambda!" } } }
      • SQSState 將傳回下列值:

        "0":{ "Return":{ "MD5OfMessageBody":"3bcb6e8e-7h85-4375-b0bc-1a59812c6e51", "MessageId":"3bcb6e8e-8b51-4375-b0bc-1a59812c6e51" } }
    • RetryPath - 此測試MockedSQSSuccess會分別模擬 LambdaStateSQSState 使用 MockedLambdaRetry 和 的輸出。此外, LambdaState 設定為執行四次重試嘗試。這些嘗試的模擬回應會在 MockedLambdaRetry 狀態中定義和編製索引。

      • 初始嘗試的結尾是任務失敗,其中包含原因和錯誤訊息,如下列範例所示:

        "0":{ "Throw": { "Error": "Lambda.ResourceNotReadyException", "Cause": "Lambda resource is not ready." } }
      • 第一次和第二次重試嘗試的結尾是任務失敗,其中包含原因和錯誤訊息,如下列範例所示:

        "1-2":{ "Throw": { "Error": "Lambda.TimeoutException", "Cause": "Lambda timed out." } }
      • 第三次重試嘗試的結尾是任務成功,其中包含模擬 Lambda 回應中承載區段的狀態結果。

        "3":{ "Return": { "StatusCode": 200, "Payload": { "StatusCode": 200, "body": "Hello from Lambda!" } } }
        注意
        • 對於具有重試政策的狀態,Step Functions Local 會耗盡政策中設定的重試嘗試,直到收到成功回應為止。這表示您必須針對連續嘗試次數的重試表示模擬,並應涵蓋所有重試嘗試,才能傳回成功回應。

        • 如果您未針對特定重試嘗試指定模擬回應,例如重試 "3",狀態機器執行將會失敗。

    • HybridPath - 此測試模擬 的輸出LambdaState。成功LambdaState執行並收到模擬資料做為回應後, 會對生產中指定的資源SQSState執行實際服務呼叫。

    如需如何使用模擬服務整合開始測試執行的詳細資訊,請參閱步驟 3:執行模擬服務整合測試

  2. 確定模擬回應的結構符合您在進行整合服務呼叫時收到的實際服務回應結構。如需模擬回應的結構需求資訊,請參閱 設定模擬服務整合

    在先前的範例模擬組態檔案中,在 中定義的模擬回應MockedLambdaRetryMockedLambdaSuccess符合從呼叫 傳回的實際回應結構HelloFromLambda

    重要

    AWS 服務回應在不同服務之間的結構可能有所不同。Step Functions Local 不會驗證模擬回應結構是否符合實際的服務回應結構。您必須先確保您的模擬回應符合實際回應,再進行測試。若要檢閱服務回應的結構,您可以使用 Step Functions 執行實際的服務呼叫,或檢視這些服務的文件。

步驟 2:將模擬組態檔案提供給 Step Functions Local

您可以透過下列其中一種方式,將模擬組態檔案提供給 Step Functions Local:

Docker
注意

如果您使用的是 Step Functions Local 的 Docker 版本,您只能使用環境變數提供模擬組態檔案。此外,您必須在初始伺服器開機時,將模擬組態檔案掛載至 Step Functions Local 容器。

將模擬組態檔案掛載到 Step Functions Local 容器內的任何目錄。然後,設定名為 的環境變數SFN_MOCK_CONFIG,其中包含容器中模擬組態檔案的路徑。只要環境變數包含檔案路徑和名稱,此方法就能將模擬組態檔案命名為任何項目。

下列命令顯示啟動 Docker 映像的格式。

docker run -p 8083:8083 --mount type=bind,readonly,source={absolute path to mock config file},destination=/home/StepFunctionsLocal/MockConfigFile.json -e SFN_MOCK_CONFIG="/home/StepFunctionsLocal/MockConfigFile.json" amazon/aws-stepfunctions-local

下列範例使用 命令來啟動 Docker 映像。

docker run -p 8083:8083 --mount type=bind,readonly,source=/Users/admin/Desktop/workplace/MockConfigFile.json,destination=/home/StepFunctionsLocal/MockConfigFile.json -e SFN_MOCK_CONFIG="/home/StepFunctionsLocal/MockConfigFile.json" amazon/aws-stepfunctions-local
JAR File

使用下列其中一種方式,將模擬組態檔案提供給 Step Functions Local:

  • 將模擬組態檔案放在與 相同的目錄中Step FunctionsLocal.jar。使用此方法時,您必須命名模擬組態檔案 MockConfigFile.json

  • 在執行 Step Functions Local 的工作階段中,將名為 的環境變數設定為模擬組態檔案SFN_MOCK_CONFIG的完整路徑。只要環境變數包含其檔案路徑和名稱,此方法就可讓模擬組態檔案命名為任何項目。在下列範例中, SFN_MOCK_CONFIG變數設定為指向EnvSpecifiedMockConfig.json位於 /home/workspace目錄中名為 的模擬組態檔案。

    export SFN_MOCK_CONFIG="/home/workspace/EnvSpecifiedMockConfig.json"
注意
  • 如果您未將環境變數提供給 SFN_MOCK_CONFIG Step Functions Local,預設會嘗試讀取您啟動 Step Functions Local MockConfigFile.json的目錄中名為 的模擬組態檔案。

  • 如果您將模擬組態檔案放在與 相同的目錄中,Step FunctionsLocal.jar並設定環境變數 SFN_MOCK_CONFIG,Step Functions Local 會讀取環境變數指定的檔案。

步驟 3:執行模擬服務整合測試

在您建立並提供模擬組態檔案給 Step Functions Local 之後,請使用模擬服務整合執行模擬組態檔案中設定的狀態機器。然後使用 API動作檢查執行結果。

  1. 根據模擬組態檔案中先前提及的定義建立狀態機器。

    aws stepfunctions create-state-machine \ --endpoint http://localhost:8083 \ --definition "{\"Comment\":\"Thisstatemachineiscalled:LambdaSQSIntegration\",\"StartAt\":\"LambdaState\",\"States\":{\"LambdaState\":{\"Type\":\"Task\",\"Resource\":\"arn:aws:states:::lambda:invoke\",\"Parameters\":{\"Payload.$\":\"$\",\"FunctionName\":\"arn:aws:lambda:us-east-1:123456789012:function:HelloWorldFunction\"},\"Retry\":[{\"ErrorEquals\":[\"States.ALL\"],\"IntervalSeconds\":2,\"MaxAttempts\":3,\"BackoffRate\":2}],\"Next\":\"SQSState\"},\"SQSState\":{\"Type\":\"Task\",\"Resource\":\"arn:aws:states:::sqs:sendMessage\",\"Parameters\":{\"QueueUrl\":\"https://sqs.us-east-1.amazonaws.com/123456789012/myQueue\",\"MessageBody.$\":\"$\"},\"End\":true}}}" \ --name "LambdaSQSIntegration" --role-arn "arn:aws:iam::123456789012:role/service-role/LambdaSQSIntegration"
  2. 使用模擬服務整合執行狀態機器。

    若要使用模擬組態檔案,請在模擬組態檔案中設定的狀態機器上StartExecutionAPI撥打電話。若要這樣做,請將尾碼 附加#test_name至 ARN所使用的狀態機器StartExecutiontest_name 是測試案例,會針對相同模擬組態檔案中的狀態機器進行設定。

    下列命令是使用 LambdaSQSIntegration 狀態機器和模擬組態的範例。在此範例中,LambdaSQSIntegration狀態機器會使用 中定義的HappyPath測試來執行步驟 1:在模擬組態檔案中指定模擬服務整合HappyPath 測試包含執行的組態,以處理使用 LambdaState和模擬服務回應所SQSState發出的MockedLambdaSuccessMockedSQSSuccess模擬服務整合呼叫。

    aws stepfunctions start-execution \ --endpoint http://localhost:8083 \ --name executionWithHappyPathMockedServices \ --state-machine arn:aws:states:us-east-1:123456789012:stateMachine:LambdaSQSIntegration#HappyPath
  3. 檢視狀態機器執行回應。

    StartExecution 使用模擬服務整合測試呼叫的回應與StartExecution正常呼叫的回應相同,這會傳回執行ARN和開始日期。

    以下是StartExecution使用模擬服務整合測試呼叫 的範例回應:

    { "startDate":"2022-01-28T15:03:16.981000-05:00", "executionArn":"arn:aws:states:us-east-1:123456789012:execution:LambdaSQSIntegration:executionWithHappyPathMockedServices" }
  4. 透過發出 ListExecutionsDescribeExecutionGetExecutionHistoryAPI呼叫來檢查執行的結果。

    aws stepfunctions get-execution-history \ --endpoint http://localhost:8083 \ --execution-arn arn:aws:states:us-east-1:123456789012:execution:LambdaSQSIntegration:executionWithHappyPathMockedServices

    下列範例示範GetExecutionHistory使用步驟 2 中所示ARN範例回應中的執行呼叫 的回應部分。在此範例中, LambdaState和 的輸出SQSState是模擬組態檔案中定義的MockedLambdaSuccessMockedSQSSuccess模擬資料。 步驟 1:在模擬組態檔案中指定模擬服務整合此外,模擬資料的使用方式與執行實際服務整合呼叫時傳回的資料使用方式相同。此外,在此範例中,來自 的輸出LambdaStateSQSState做為輸入傳遞至 。

    { "events": [ ... { "timestamp": "2021-12-02T19:39:48.988000+00:00", "type": "TaskStateEntered", "id": 2, "previousEventId": 0, "stateEnteredEventDetails": { "name": "LambdaState", "input": "{}", "inputDetails": { "truncated": false } } }, ... { "timestamp": "2021-11-25T23:39:10.587000+00:00", "type": "LambdaFunctionSucceeded", "id": 5, "previousEventId": 4, "lambdaFunctionSucceededEventDetails": { "output": "{\"statusCode\":200,\"body\":\"\\\"Hello from Lambda!\\\"\"}", "outputDetails": { "truncated": false } } }, ... "timestamp": "2021-12-02T19:39:49.464000+00:00", "type": "TaskStateEntered", "id": 7, "previousEventId": 6, "stateEnteredEventDetails": { "name": "SQSState", "input": "{\"statusCode\":200,\"body\":\"\\\"Hello from Lambda!\\\"\"}", "inputDetails": { "truncated": false } } }, ... { "timestamp": "2021-11-25T23:39:10.652000+00:00", "type": "TaskSucceeded", "id": 10, "previousEventId": 9, "taskSucceededEventDetails": { "resourceType": "sqs", "resource": "sendMessage", "output": "{\"MD5OfMessageBody\":\"3bcb6e8e-7h85-4375-b0bc-1a59812c6e51\",\"MessageId\":\"3bcb6e8e-8b51-4375-b0bc-1a59812c6e51\"}", "outputDetails": { "truncated": false } } }, ... ] }

Step Functions 中模擬服務整合的組態檔案

不支援 Step Functions Local

Step Functions Local 不提供功能同位,且不受支援

您可以考慮模擬 Step Functions 的第三方解決方案,用於測試目的。

若要使用模擬服務整合,您必須先建立名為 的模擬組態檔案,MockConfigFile.json其中包含您的模擬組態。然後將 Step Functions Local 與模擬組態檔案一起提供。此組態檔案會定義測試案例,其中包含使用模擬服務整合回應的模擬狀態。下一節包含模擬組態結構的相關資訊,其中包含模擬狀態和模擬回應:

模擬組態檔案結構

模擬組態是包含下列最上層欄位的JSON物件:

  • StateMachines - 此物件的欄位代表設定為使用模擬服務整合的狀態機器。

  • MockedResponse - 此物件的欄位代表服務整合呼叫的模擬回應。

以下是模擬組態檔案的範例,其中包含 StateMachine定義和 MockedResponse

{ "StateMachines":{ "LambdaSQSIntegration":{ "TestCases":{ "HappyPath":{ "LambdaState":"MockedLambdaSuccess", "SQSState":"MockedSQSSuccess" }, "RetryPath":{ "LambdaState":"MockedLambdaRetry", "SQSState":"MockedSQSSuccess" }, "HybridPath":{ "LambdaState":"MockedLambdaSuccess" } } } }, "MockedResponses":{ "MockedLambdaSuccess":{ "0":{ "Return":{ "StatusCode":200, "Payload":{ "StatusCode":200, "body":"Hello from Lambda!" } } } }, "LambdaMockedResourceNotReady":{ "0":{ "Throw":{ "Error":"Lambda.ResourceNotReadyException", "Cause":"Lambda resource is not ready." } } }, "MockedSQSSuccess":{ "0":{ "Return":{ "MD5OfMessageBody":"3bcb6e8e-7h85-4375-b0bc-1a59812c6e51", "MessageId":"3bcb6e8e-8b51-4375-b0bc-1a59812c6e51" } } }, "MockedLambdaRetry":{ "0":{ "Throw":{ "Error":"Lambda.ResourceNotReadyException", "Cause":"Lambda resource is not ready." } }, "1-2":{ "Throw":{ "Error":"Lambda.TimeoutException", "Cause":"Lambda timed out." } }, "3":{ "Return":{ "StatusCode":200, "Payload":{ "StatusCode":200, "body":"Hello from Lambda!" } } } } } }

模擬組態欄位參考

下列各節說明您必須於模擬組態中定義的最上層物件欄位。

StateMachines

StateMachines 物件定義哪些狀態機器將使用模擬服務整合。每個狀態機器的組態會以 的最上層欄位表示StateMachines。欄位名稱是狀態機器的名稱,而值是包含名為 的單一欄位的物件TestCases,其欄位代表該狀態機器的測試案例。

下列語法顯示具有兩個測試案例的狀態機器:

"MyStateMachine": { "TestCases": { "HappyPath": { ... }, "SadPath": { ... } }
TestCases

的欄位TestCases代表狀態機器的個別測試案例。每個測試案例的名稱在每個狀態機器上必須是唯一的,每個測試案例的值都是指定用於狀態機器中任務狀態的模擬回應的物件。

下列範例會將兩個Task狀態TestCase連結至兩個 MockedResponses

"HappyPath": { "SomeTaskState": "SomeMockedResponse", "AnotherTaskState": "AnotherMockedResponse" }
MockedResponses

MockedResponses 是包含多個模擬回應物件的物件,具有唯一的欄位名稱。模擬回應物件會為每個模擬任務狀態的叫用定義成功的結果或錯誤輸出。您可以使用個別整數字串指定叫用號碼,例如 “0”、“1”、“2” 和 “3”,或包含整數的範圍,例如 “0-1”、“2-3”。

當您模擬任務時,您必須為每個調用指定模擬回應。回應必須包含名為 Return或 的單一欄位,Throw其值是模擬任務調用的結果或錯誤輸出。如果您未指定模擬回應,狀態機器執行將會失敗。

以下是MockedResponse具有 ThrowReturn 物件的 範例。在此範例中,前三次執行狀態機器、"0-2"傳回在 中指定的回應,以及第四次執行狀態機器時,"3"傳回在 中指定的回應。

"SomeMockedResponse": { "0-2": { "Throw": { ... } }, "3": { "Return": { ... } } }
注意

如果您使用的是 Map 狀態,而且想要確保Map狀態的可預測回應,請將 值設定為 maxConcurrency 1。如果您將值設定為大於 1,Step Functions Local 會同時執行多個反覆運算,這會導致跨反覆運算的狀態整體執行順序無法預測。這可能會進一步導致 Step Functions Local 使用不同的模擬回應,以從一個執行到下一個執行的反覆運算狀態。

傳回

ReturnMockedResponse物件的欄位表示。它指定模擬任務狀態的成功結果。

以下是包含模擬回應的Return物件範例,用於Invoke呼叫 Lambda 函數:

"Return": { "StatusCode": 200, "Payload": { "StatusCode": 200, "body": "Hello from Lambda!" } }
擲回

ThrowMockedResponse物件的欄位表示。它指定失敗任務的錯誤輸出。的值Throw必須是包含 Error和具有字串值Cause欄位的物件。此外,您在 中於 Error 欄位指定的字串值,MockConfigFile.json必須符合 狀態機器的 RetryCatch區段中處理的錯誤。

以下是包含模擬回應的Throw物件範例,用於Invoke呼叫 Lambda 函數:

"Throw": { "Error": "Lambda.TimeoutException", "Cause": "Lambda timed out." }