Skip to content

Commit 5953051

Browse files
author
Jordi Macià
committed
Review pull request #228 feedback
1 parent 8cbc90d commit 5953051

File tree

5 files changed

+28384
-18
lines changed

5 files changed

+28384
-18
lines changed
Lines changed: 158 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,177 @@
1-
## Step Functions Local Testing using Jest
1+
[![typescript: 4.5.5](https://badgen.net/badge/Built%20With/TypeScript/blue9)](https://badgen.net/badge/Built%20With/TypeScript/blue9)
2+
[![AWS:Step Functions](https://img.shields.io/badge/AWS-Step%20Functions-blueviolet)](https://img.shields.io/badge/Step%20Functions-blueviolet)
3+
[![test: unit](https://img.shields.io/badge/Test-Unit-blue)](https://img.shields.io/badge/Test-Unit-blue)
4+
5+
# Typescript: AWS Step Functions Local Testing using Jest Example
6+
7+
## Introduction
8+
29
[Step Functions Local testing with mock configuration](https://aws.amazon.com/blogs/compute/mocking-service-integrations-with-aws-step-functions-local/)
310
provides the capability to mock AWS service integrations that are present in a state machine. This helps in testing the
411
state machine in isolation.
512

6-
This is sample project which showcases how to run Step Functions local tests with mocks using Jest instead of running ad-hoc CLI commands. [Testcontainers](https://www.testcontainers.org/) is used to run [Step Functions Local Docker image](https://docs.aws.amazon.com/step-functions/latest/dg/sfn-local-docker.html).
13+
This is a sample project which showcases how to run Step Functions local tests with mocks using Jest instead of running ad-hoc CLI commands. [Testcontainers](https://www.testcontainers.org/) is used to run the [Step Functions Local Docker image](https://docs.aws.amazon.com/step-functions/latest/dg/sfn-local-docker.html).
714

8-
This is not a replacement of the strategy shown in above blog but another way to test Step Functions state machine with
15+
This is not a replacement of the strategy shown in the blog above but another way to test Step Functions state machine with
916
better assertion capabilities. Teams currently using Javascript / Typescript for Serverless development can leverage this strategy in their
1017
current applications.
1118

19+
---
20+
21+
## Contents
22+
23+
- [Introduction](#introduction)
24+
- [Contents](#contents)
25+
- [About this Pattern](#about-this-pattern)
26+
- [About this Example](#about-this-example)
27+
- [Key Files in the Project](#key-files-in-the-project)
28+
- [Sample project description](#sample-project-description)
29+
- [Unit Test](#unit-test)
30+
- [Integration Test](#integration-test)
31+
32+
---
33+
34+
## About this Pattern
35+
36+
### System Under Test (SUT)
37+
38+
The SUT is a sales lead generation sample workflow implemented with AWS Step Functions. In this example, new sales leads are created in a customer relationship management system. This triggers the sample workflow execution using [input data](events/sfn_valid_input.json), which provides information about the contact.
39+
40+
Using the sales lead data, the workflow first validates the contact’s identity and address. If valid, it uses Step Functions’ AWS SDK integration for [Amazon Comprehend](https://docs.aws.amazon.com/comprehend/latest/dg/how-sentiment.html) to call the [DetectSentiment](https://docs.aws.amazon.com/comprehend/latest/dg/API_DetectSentiment.html) API. It uses the sales lead’s comments as input for sentiment analysis.
41+
42+
If the comments have a positive sentiment, it adds the sales leads information to a DynamoDB table for follow-up. The event is published to [Amazon EventBridge](https://aws.amazon.com/eventbridge/) to notify subscribers.
43+
44+
If the sales lead data is invalid or a negative sentiment is detected, it publishes events to EventBridge for notification. No record is added to the [Amazon DynamoDB](https://aws.amazon.com/dynamodb/) table. The following Step Functions Workflow Studio diagram shows the control logic:
45+
46+
![System Under Test (SUT)](images/stepfunctions_local_test.png)
47+
48+
### Goal
49+
50+
The goal of this example is to test AWS Step Functions state machines in isolation using mocked responses for the external services which need to conform to actual responses before testing. With mocking, developers get more control over the type of scenarios that a state machine can handle, leading to assertion of multiple behaviors. Testing a state machine with mocks can also be part of the software release. Asserting on behaviors like error handling, branching, parallel, dynamic parallel (map state) helps test the entire state machine’s behavior. For any new behavior in the state machine, such as a new type of exception from a state, you can mock and add as a test.
51+
52+
### Description
53+
54+
In this example, you test a scenario in which:
55+
56+
1. The identity and address are successfully validated using a Lambda function.
57+
2. A positive sentiment is detected using the Comprehend.DetectSentiment API after three retries.
58+
3. A contact item is written to a DynamoDB table successfully
59+
4. An event is published to an EventBridge event bus successfully
60+
61+
The execution path for this test scenario is shown in the following diagram (the red and green numbers have been added). 0 represents the first execution; 1, 2, and 3 represent the max retry attempts (MaxAttempts), in case of an InternalServerException.
62+
63+
![System Under Test Description (SUT)](images/system-under-test-description.png)
64+
65+
[Top](#contents)
66+
67+
---
68+
69+
## About this Example
70+
71+
To use service integration mocking, [create a mock configuration file](https://docs.aws.amazon.com/step-functions/latest/dg/sfn-local-test-sm-exec.html) with sections specifying mock AWS service responses. These are grouped into test cases that can be activated when executing state machines locally. The following example provides code snippets and the full mock configuration is available in the [code repository](statemachine/test/MockConfigFile.json).
72+
73+
To mock a successful Lambda function invocation, define a mock response that conforms to the [Lambda.Invoke](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_ResponseElements) API response elements. Associate it to the first request attempt:
74+
75+
```json
76+
"CheckIdentityLambdaMockedSuccess": {
77+
"0": {
78+
"Return": {
79+
"StatusCode": 200,
80+
"Payload": {
81+
"statusCode": 200,
82+
"body": "{\"approved\":true,\"message\":\"identity validation passed\"}"
83+
}
84+
}
85+
}
86+
}
87+
```
88+
89+
To mock the DetectSentiment retry behavior, define failure and successful mock responses that conform to the [Comprehend.DetectSentiment](https://docs.aws.amazon.com/comprehend/latest/dg/API_DetectSentiment.html#API_DetectSentiment_ResponseElements) API call. Associate the failure mocks to three request attempts, and associate the successful mock to the fourth attempt:
90+
91+
```json
92+
"DetectSentimentRetryOnErrorWithSuccess": {
93+
"0-2": {
94+
"Throw": {
95+
"Error": "InternalServerException",
96+
"Cause": "Server Exception while calling DetectSentiment API in Comprehend Service"
97+
}
98+
},
99+
"3": {
100+
"Return": {
101+
"Sentiment": "POSITIVE",
102+
"SentimentScore": {
103+
"Mixed": 0.00012647535,
104+
"Negative": 0.00008031699,
105+
"Neutral": 0.0051454515,
106+
"Positive": 0.9946478
107+
}
108+
}
109+
}
110+
}
111+
112+
```
113+
114+
Note that Step Functions Local does not validate the structure of the mocked responses. Ensure that your mocked responses conform to actual responses before testing. To review the structure of service responses, either perform the actual service calls using Step Functions or view the documentation for those services.
115+
116+
Next, associate the mocked responses to a test case identifier:
117+
118+
```json
119+
"RetryOnServiceExceptionTest": {
120+
"Check Identity": "CheckIdentityLambdaMockedSuccess",
121+
"Check Address": "CheckAddressLambdaMockedSuccess",
122+
"DetectSentiment": "DetectSentimentRetryOnErrorWithSuccess",
123+
"Add to FollowUp": "AddToFollowUpSuccess",
124+
"CustomerAddedToFollowup": "CustomerAddedToFollowupSuccess"
125+
}
126+
```
127+
128+
With the test case and mock responses configured, you can use them for testing with Step Functions Local.
129+
130+
### Key Files in the Project
131+
132+
- [local_testing.asl.json](statemachine/local_testing.asl.json) - State machine definition in ASL
133+
- [sfn_valid_input.json](events/sfn_valid_input.json) - State machine unit test input event
134+
- [MockConfigFile.json](statemachine/test/MockConfigFile.json) - Unit test mocked responses
135+
- [step-functions-local.test.ts](src/tests/sfnLocal/step-functions-local.test.ts) - Unit tests definition
136+
137+
[Top](#contents)
138+
139+
---
140+
141+
## Unit Test
142+
12143
### Prerequisites
13144
- Node.js v14 or newer
14-
- [Jest](https://jestjs.io/docs/getting-started)
15-
- [Testcontainers](https://www.testcontainers.org/)
16145
- [Docker](https://www.docker.com/)
146+
147+
### Unit Test description
148+
149+
This example contains a [sample event](events/sfn_valid_input.json) with new user registration data to be processed by the state machine. The unit tests will check how the state machine behaves for each of the following scenarios defined in the [MockConfigFile.json](statemachine/test/MockConfigFile.json) file:
17150

18-
### Running Tests
151+
- `HappyPathTest`: every external service runs succesfully and the state machine exits with "CustomerAddedToFollowup".
152+
- `NegativeSentimentTest`: the contact details are properly formatted, a negative sentiment is detected within the user comments and the state machine exits with "NegativeSentimentDetected".
153+
- `RetryOnServiceExceptionTest`: the sentiment detection service fails three times and the state machine retries until successfully retrieving the sentiment in the fourth attempt.
154+
155+
### Run the Unit Test
19156
> Make sure docker engine is running before running the tests.
20157
21-
In order to install the dependencies, just run below command from project "src" subdirectory:
22-
```bash
23-
npm install
158+
``` shell
159+
step-functions-local$ docker version
160+
Client: Docker Engine - Community
161+
Cloud integration: v1.0.29
162+
Version: 20.10.21
163+
API version: 1.41
164+
...
24165
```
25166

26-
In order to run the tests, just run below command from project "src" subdirectory:
27-
```bash
28-
npm run test
167+
To run the unit tests:
168+
169+
``` shell
170+
step-functions-local$ cd src
171+
src $ npm install
172+
src $ npm run test
29173
```
30174

31-
### Explanation
32-
Checkout this file for details:
175+
[Top](#contents)
33176

34-
- [`step-functions-local.test.ts`](src/tests/sfnLocal/step-functions-local.test.ts)
177+
---
Loading

0 commit comments

Comments
 (0)