Test Step Function with CDK - Best Practice

0

I created a simple test function with a task that invokes lambda.

    Function weatherToday = Function.Builder.create(this, "WeatherToday")
        .code(Code.fromAsset(getClass().getClassLoader().getResource("lambda/weather_today").getPath()))
        .runtime(Runtime.NODEJS_14_X)
        .architecture(Architecture.ARM_64)
        .handler("WeatherToday.handler")
        .timeout(Duration.seconds(25))
        .build();

    IChainable getCurrentWeather = LambdaInvoke.Builder.create(this, "Get Current Weather")
        .lambdaFunction(weatherToday)
        .retryOnServiceExceptions(true)
        .build();

    Pass hotState = new Pass(this, "It is HOT!");
    Pass coldState = new Pass(this, "It is COLD!!");

    Choice isItHot = new Choice(this, "Is it Hot?")
        .when(Condition.numberGreaterThanEquals("$.Payload.temp_f", 90), hotState)
        .otherwise(coldState);

    IChainable chain = Chain.start(getCurrentWeather).next(isItHot);

    StateMachine.Builder.create(this, "IsItHotNow").definition(chain).timeout(Duration.seconds(60))// best practice
        .build();
  }

Assuming this is the best practice, I wanted to write a test that checks whether the states transition or are chained as intended. When pulling in the DefinitionString for the given state function

 "DefinitionString": {
          "Fn::Join": [
            "",
            [
              "{\"StartAt\":\"Get Current Weather\",\"States\":{\"Get Current Weather\":{\"Next\":\"Is it Hot?\",\"Retry\":[{\"ErrorEquals\":[\"Lambda.ServiceException\",\"Lambda.AWSLambdaException\",\"Lambda.SdkClientException\"],\"IntervalSeconds\":2,\"MaxAttempts\":6,\"BackoffRate\":2}],\"Type\":\"Task\",\"Resource\":\"arn:",
              {
                "Ref": "AWS::Partition"
              },
              ":states:::lambda:invoke\",\"Parameters\":{\"FunctionName\":\"",
              {
                "Fn::GetAtt": [
                  "WeatherToday53196B63",
                  "Arn"
                ]
              },
              "\",\"Payload.$\":\"$\"}},\"Is it Hot?\":{\"Type\":\"Choice\",\"Choices\":[{\"Variable\":\"$.Payload.temp_f\",\"NumericGreaterThanEquals\":90,\"Next\":\"It is HOT!\"}],\"Default\":\"It is COLD!!\"},\"It is COLD!!\":{\"Type\":\"Pass\",\"End\":true},\"It is HOT!\":{\"Type\":\"Pass\",\"End\":true}},\"TimeoutSeconds\":60}"
            ]
          ]
        }

The above is an array of strings with inlined intrinsic ASL functions. There does not seem to be a good way to get the state definitions to resemble the typical state function definition file as json without the intrinsic functions. My thoughts are if I can get the appropriate state machine definition as a json format of ASL it will be easier to test for the expected states.

Please let me know if there is a way to do this or what may be the best practice approach?

已提问 2 年前67 查看次数
1 回答
0

Hello! This Fine-grained assertions section (at the bottom of that section there is a Step Function example) may be of help that makes use of the assertions module. In particular for Step Function definitions, the Match.serializedJson() matcher might be useful. In theory that could help you assert your Tasks are transitioning or chaining as expected.

Another approach using the Matching lib could be something like the following (Typescript snippet example)

...
    it('Get Current Weather should transition to "Is it Hot?", () => {
      const GET_WEATHER= 'Get Current Weather'
      const IS_IT_HOT = "Is it Hot?"
      template.hasResourceProperties('AWS::StepFunctions::StateMachine', {
        DefinitionString: {
          'Fn::Join': [
            '',
            Match.arrayWith([
              Match.stringLikeRegexp(
                `("${GET_WEATHER}":{"Next":"${IS_IT_HOT}").*`,
              ),
            ]),
          ],
        },
      });
    });
...

Hope this gives you some ideas!

David
已回答 13 天前

您未登录。 登录 发布回答。

一个好的回答可以清楚地解答问题和提供建设性反馈,并能促进提问者的职业发展。

回答问题的准则