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 年前檢視次數 66 次
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 天前

您尚未登入。 登入 去張貼答案。

一個好的回答可以清楚地回答問題並提供建設性的意見回饋,同時有助於提問者的專業成長。

回答問題指南