Mock DynamoDB Services
We all understand the importance of mocking real services. Without moking, a service can give unexpected result after a few update and delete operations. With mocking, the result of GET will never change, no matter how many times you UPDATE.
The purpose of this article is to explain how to create mocked DynamoDb web services. Though some of the scenarios are not valid for functional tests they are explained for learning purpose only.
Prerequisite
We’re using stubmatic npm package to create mock service. But, you may choose any method of your choice.
Stubmatic is designed specially for testing. It gives many advance features to mock web services. In stubmatic, we create a request-response mapping file which is easy enough to understand. The stub data can be exterlized to the file system.
npm i -g stubmatic
Let’s Mock
Before we jump to a particular scenario, please remember that DynamoDB service expect following headers with valid values;
- x-amz-target
- authorization
So we’ll confirm in our mocks that these headers are coming in request. However, we’ll not check for their valid values.
Create a file say mapping.yaml and copy paste the code mentioned in each scenario.
- Scenario: mandatory header ‘x-amz-target’ is missing
Below mapping will match a request without x-amz-target
header.
- request:
method: POST
url: /dynamodb
headers:
x-amz-target: ^
response:
body: >
{
"__type": "com.amazonaws.dynamodb.v20120810#InternalFailure",
"message": "The request processing has failed because of an unknown error, exception or failure."
}
status: 500
headers:
Content-type: application/json
As you’ll be trusting on a db client already tested, you’ll not need to test this scenario in your FTs. Similarliy, you can check for authorization
header.
2. Scenario: table doesn’t exist
This is another unfit scenario for the FTs so we’re not creating mapping for this. However, this is the response received from DynamoDB with status 400 when the table name mentioned in any request is not created yet.
{
"__type": "com.amazonaws.dynamodb.v20120810#ResourceNotFoundException",
"message": "Cannot do operations on a non-existent table"
3. Scenario: key doesn’t exist
This is one more mistake we may do. DynamoDb returns following response when they key used in the query/request doesn’t match with the key created for the table.
{
"__type": "com.amazon.coral.validate#ValidationException",
"message": "One of the required keys was not given a value"
}
I don’t see any valid case when you should mock such scenarios.
4. Scenario: data doesn’t exist
This is the perfect case to test in your functional tests when there is no data present against the key you passed.
- request:
method: POST
url: /dynamodb
headers:
content-type: application/x-amz-json-1.0
x-amz-target: .*GetItem
authorization: .*
post: "Key":{"user_id":{"S":"amitgupta9"}} response:
body: {}
state:
headers:
Content-type: application/json
Though it depends on the business scenario but you should always has one to one mapping between the request and response.
5. Scenario: return some data
- request:
method: POST
url: /dynamodb
headers:
content-type: application/x-amz-json-1.0
x-amz-target: .*GetItem
authorization: .*
post: "Key":{"user_id":{"S":"amitgupta_official"}}response:
body: >
{
"Item": {
"user_id": {
"S": "amitgupta_official"
},
"name": {
"S": "amit gupta"
},
"website": {
"S": "https://amitkumargupta.work"
}
}
}
state:
headers:
Content-type: application/json
6. Scenario: put some data
- request:
method: POST
url: /dynamodb
headers:
content-type: application/x-amz-json-1.0
x-amz-target: .*PutItem
authorization: .*
post: "Item":{"user_id":{"S":"amitgupta9"}response:
body: {}
state:
headers:
Content-type: application/json
Your mapping.yaml is having 5 mappings at this time. Now you have to just run the stubmatic to read the mappings and you’re all set. Create a config file and mentioned it in following command to run your mocked DynamoDB server;
$ stubmatic -p 8000 -h localhost -c config.json
You can skip -h
as localhost is by default.
If you’re running the DynamoDB locally, run the following command once you download it;
$ java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb
You can also install npm package dynamodb-admin
. It’ll provide a GUI running in browser to explore the tables and data in DynamoDB.
In last
What if we’ve missed some scenarios? Run the stubmatic as proxy to debug passing traffic and create the stubs based on that. For this, run you application to connect to DynamoDB on port 8001. But run the DynamoDB locally on port 8000. Now run the following command from any folder;
$ stubmatic -v --debug -p 8001 --to http://localhost:8000
In above command, stubmatic will run in debug mode on port 8001 and pass all the traffic to DynamoDb service running on localhost:8000
. It’ll log all request and response on the console.
Please leave comments with your doubts and queries. I would be happy to solve them.
If you like this article, please clap. You can clap many times. It doesn’t require functional testing.
Feedback
Feedbacks are important to understand how can I improve and bring more useful materials. Please clap this article, comment here, or please give a star to stubmatic github repository.