使用模拟服务集成 - Amazon Step Functions
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用模拟服务集成

在 Step Functions Local 中,您可以使用模拟服务集成来测试状态机的执行路径,而无需实际调用集成服务。要将状态机配置为使用模拟服务集成,请创建一个模拟配置文件。在此文件中,您可以将服务集成的所需输出定义为模拟响应,并将使用模拟响应模拟执行路径的执行定义为测试用例。

通过向 Step Functions Local 提供模拟配置文件,您可以通过运行使用测试用例中指定模拟响应的状态机来测试服务集成调用,而无需进行实际的服务集成调用。

注意

如果您未在模拟配置文件中指定模拟服务集成响应,Step Functions Local 将使用您在设置 Step Functions Local 时配置的端点调用 Amazon 服务集成。有关为 Step Functions Local 配置端点的信息,请参阅为 Step Functions Local 设置配置选项

本主题中的关键概念

本主题使用以下列表中定义的几个概念:

  • 模拟服务集成 - 指配置为使用模拟响应而非执行实际服务调用的 Task 状态。

  • 模拟响应 - 指 Task 状态可以配置为使用的模拟数据。

  • 测试用例 - 指配置为使用模拟服务集成的状态机执行。

  • 模拟配置文件 - 指包含 JSON 的模拟配置文件,该文件定义了模拟服务集成、模拟响应和测试用例。

第 1 步:在模拟配置文件中指定模拟服务集成

你可以使用 Step Functions Local 测试 Step Functions Amazon SDK 和优化的服务集成。下图展示了在状态机定义选项卡中定义的状态机:


        模拟服务集成示例。

为此,您必须创建一个模拟配置文件,其中包含模拟配置结构简介中定义的部分。

  1. 创建一个名为 MockConfigFile.json 的文件,以便使用模拟服务集成配置测试。

    以下示例展示了一个引用状态机的模拟配置文件,该状态机有两个已定义的状态,分别名为 LambdaStateSQSState

    Mock configuration file example

    以下是一个模拟配置文件示例,演示了如何模拟调用 Lambda 函数向 Amazon SQS 发送消息所产生的响应。在此示例中,LambdaSQSIntegration 状态机包含三个测试用例,分别名为 HappyPathRetryPathHybridPath,它们模拟名为 LambdaStateSQSStateTask 状态。这些状态使用 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 的状态机定义示例,它定义了两个名为 LambdaStateSQSState 的服务集成任务状态。LambdaState 包含基于 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 - 该测试分别使用 MockedLambdaSuccessMockedSQSSuccess 模拟 LambdaStateSQSState 的输出。

      • 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 - 该测试分别使用 MockedLambdaRetryMockedSQSSuccess 模拟 LambdaStateSQSState 的输出。此外,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. 确保模拟响应的结构符合您在调用集成服务时收到的实际服务响应的结构。有关模拟响应的结构要求信息,请参阅配置模拟服务集成

    在前面的示例模拟配置文件中,MockedLambdaSuccessMockedLambdaRetry 中定义的模拟响应与调用 HelloFromLambda 时返回的实际响应结构一致。

    重要

    Amazon 服务不同,响应结构可能会不同。Step Functions Local 不会验证模拟响应结构是否符合实际的服务响应结构。在测试之前,您必须确保模拟响应符合实际响应。要查看服务响应的结构,您可以使用 Step Functions 执行实际的服务调用,也可以查看这些服务的文档。

第 2 步:向 Step Functions Local 提供模拟配置文件

您可以通过以下方式将模拟配置文件提供给 Step Functions Local:

Docker
注意

如果您使用的是 Docker 版本的 Step Functions Local,则只能使用环境变量提供模拟配置文件。此外,在服务器初始启动时,必须将模拟配置文件挂载到 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"
注意
  • 如果您没有向 Step Functions Local 提供环境变量 SFN_MOCK_CONFIG,则默认情况下,它将尝试读取在启动 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. 使用模拟服务集成运行状态机。

    要使用模拟配置文件,请在模拟配置文件中配置的状态机上进行 StartExecution API 调用。为此,请在 StartExecution 使用的状态机 ARN 上添加后缀 #test_nametest_name 是一个测试用例,在同一个模拟配置文件中为状态机配置。

    下面的命令是一个使用 LambdaSQSIntegration 状态机和模拟配置的示例。在此示例中,使用第 1 步:在模拟配置文件中指定模拟服务集成中定义的 HappyPath 测试来执行 LambdaSQSIntegration 状态机。HappyPath 测试包含执行配置,用于处理 LambdaStateSQSState 状态使用 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. 通过调用 ListExecutionsDescribeExecutionGetExecutionHistory API 来检查执行结果。

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

    以下示例演示了使用第 2 步所示示例响应中的执行 ARN 调用 GetExecutionHistory 的部分响应。在此示例中,LambdaStateSQSState 的输出是模拟配置文件MockedLambdaSuccessMockedSQSSuccess 中定义的模拟数据。此外,模拟数据的使用方式与执行实际服务集成调用返回的数据相同。此外,在本示例中,LambdaState 的输出作为输入传递给 SQSState

    { "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 } } }, ... ] }