Last active
May 10, 2024 16:52
-
-
Save phillip-le/3f1763c62b14ab8ad93b2923a62d8f0c to your computer and use it in GitHub Desktop.
Unit Testing AWS SDK in TypeScript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
it('should persist user to dynamodb', async () => { | |
await createUser(userInput); | |
expect(mockDynamoDbDocumentClient).toHaveReceivedCommandWith(PutCommand, { | |
TableName: 'TestUserTable', | |
Item: userToCreate, | |
}); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
it('should query user by role from dynamodb', async () => { | |
expect(mockDynamoDbDocumentClient).toHaveReceivedCommandWith(QueryCommand, { | |
TableName: config.userTableName, | |
IndexName: config.userTableRoleIndexName, | |
ExpressionAttributeNames: { '#role': 'role' }, | |
ExpressionAttributeValues: { ':role': role }, | |
KeyConditionExpression: '#role = :role', | |
}); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
it('should query user by role from dynamodb', async () => { | |
expect(queryDynamoDb).toHaveBeenCalledWith<[QueryCommandInput]>({ | |
TableName: config.userTableName, | |
IndexName: config.userTableRoleIndexName, | |
ExpressionAttributeNames: { '#role': 'role' }, | |
ExpressionAttributeValues: { ':role': role }, | |
KeyConditionExpression: '#role = :role', | |
}); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// AWS SDK v3 | |
expect(putDynamoDb).toHaveBeenCalledWith<[PutCommandInput]>({ | |
TableName: config.userTableName, | |
Item: createdUser, | |
}); | |
// AWS SDK v2 | |
expect(putDynamoDb).toHaveBeenCalledWith< | |
[DynamoDB.DocumentClient.PutItemInput] | |
>({ | |
TableName: config.userTableName, | |
Item: createdUser, | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const createUser = async (input: CreateUserInput): Promise<User> => { | |
const createdAt = new Date().toISOString(); | |
const userToCreate: User = { | |
id: randomUUID(), | |
email: input.email, | |
role: input.role, | |
createdAt, | |
updatedAt: createdAt, | |
}; | |
await dynamoDbDocumentClient.send( | |
new PutCommand({ | |
TableName: config.userTableName, | |
Item: userToCreate, | |
}), | |
); | |
return userToCreate; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const getUsersByRole = async ( | |
role: Role, | |
): Promise<GetUsersByRoleOutput> => { | |
const { Items: users } = await dynamoDbDocumentClient.send( | |
new QueryCommand({ | |
TableName: config.userTableName, | |
IndexName: config.userTableRoleIndexName, | |
ExpressionAttributeNames: { '#role': 'role' }, | |
ExpressionAttributeValues: { ':role': role }, | |
KeyConditionExpression: '#role = :role', | |
}), | |
); | |
if (!maybeUsers) { | |
return []; | |
} | |
return users as User[]; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const getUsersByRoleDynamoDb = async ( | |
role: Role, | |
): Promise<GetUsersByRoleOutput> => { | |
const { Items: users } = await queryDynamoDb({ | |
TableName: config.userTableName, | |
IndexName: config.userTableRoleIndexName, | |
ExpressionAttributeNames: { '#role': 'role' }, | |
ExpressionAttributeValues: { ':role': role }, | |
KeyConditionExpression: '#role = :role', | |
}); | |
if (!users) { | |
return []; | |
} | |
return users as User[]; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'aws-sdk-client-mock-jest'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; | |
import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb'; | |
const dynamoDbClient = new DynamoDBClient({ region: 'ap-southeast-2' }); | |
export const dynamoDbDocumentClient = | |
DynamoDBDocumentClient.from(dynamoDbClient); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
yarn add -D aws-sdk-client-mock-jest |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
yarn add -D aws-sdk-client-mock |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
yarn add @aws-sdk/client-dynamodb @aws-sdk/lib-dynamodb |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { mockClient } from 'aws-sdk-client-mock'; | |
const mockDynamoDbDocumentClient = mockClient(dynamoDbDocumentClient); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
jest.mock('../../../aws-sdk-v3/dynamodb'); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
it('should query user by role from dynamodb', async () => { | |
const role: Role = 'READER'; | |
const mockReaderUser: User = { | |
...mockUser, | |
role, | |
}; | |
jest.mocked(queryDynamoDb).mockResolvedValue({ | |
$metadata: {}, | |
Items: [mockReaderUser], | |
}); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const queryDynamoDb = async ( | |
params: DynamoDB.DocumentClient.QueryInput, | |
): Promise<DynamoDB.DocumentClient.QueryOutput> => | |
await dynamoDbDocumentClient.query(params).promise(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { Items: maybeUsers } = await dynamoDbDocumentClient | |
.query({ | |
TableName: config.userTableName, | |
IndexName: config.userTableRoleIndexName, | |
ExpressionAttributeNames: { '#role': 'role' }, | |
ExpressionAttributeValues: { ':role': role }, | |
KeyConditionExpression: '#role = :role', | |
}) | |
.promise(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
it('should create user with readonly properties and put in dynamodb', async () => { | |
mockDynamoDbDocumentClient.on(PutCommand).resolves({}); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
it('should query user by role from dynamodb', async () => { | |
const role: Role = 'READER'; | |
const mockReaderUser: User = { | |
id: 'TestUserId', | |
email: '[email protected]', | |
role, | |
createdAt: '2023-09-10T05:58:16.945Z', | |
updatedAt: '2023-09-10T05:58:16.945Z', | |
}; | |
mockDynamoDbDocumentClient.on(QueryCommand).resolves({ | |
Items: [mockReaderUser], | |
}); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
expect(putDynamoDb).toHaveBeenCalledWith<Parameters<typeof putDynamoDb>>({ | |
TableName: config.userTableName, | |
Item: createdUser, | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
it('should query user by role from dynamodb', async () => { | |
const mockReaderUser: User = { | |
id: 'TestUserId', | |
email: '[email protected]', | |
role: 'READER', | |
createdAt: '2023-09-10T05:58:16.945Z', | |
updatedAt: '2023-09-10T05:58:16.945Z', | |
}; | |
const mockQueryDynamoDb = jest.fn().mockImplementation(() => ({ | |
promise: jest.fn().mockResolvedValue({ Items: [mockReaderUser] }), | |
})); | |
jest | |
.spyOn(dynamoDbDocumentClient, 'query') | |
.mockImplementation(mockQueryDynamoDb); | |
await expect(getUsersByRole('READER')).resolves.toEqual([mockReaderUser]); | |
expect(mockQueryDynamoDb).toHaveBeenCalledWith< | |
[DynamoDB.DocumentClient.QueryInput] | |
>({ | |
TableName: config.userTableName, | |
IndexName: config.userTableRoleIndexName, | |
ExpressionAttributeNames: { '#role': 'role' }, | |
ExpressionAttributeValues: { ':role': mockReaderUser.role }, | |
KeyConditionExpression: '#role = :role', | |
}); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const queryDynamoDb = async ( | |
params: QueryCommandInput, | |
): Promise<QueryCommandOutput> => | |
await dynamoDbDocumentClient.send(new QueryCommand(params)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment