I have a simple Handler with calls getData defined in separate file
export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
let respData = await new DynamoDBClient().getData(123);
return {
statusCode: 200,
body: JSON.stringify(respData),
};
};
within my DynamoDB class, I have the following.
import { DynamoDB } from 'aws-sdk';
export default class DynamoDBClient {
private config: Config;
private client: DynamoDB.DocumentClient;
constructor() {
this.config = getConfig();
const dynamoDBClientConfig = this.config.mockDynamoDBEndpoint
? {
endpoint: this.config.mockDynamoDBEndpoint,
sslEnabled: false,
region: 'local'
}
: undefined;
this.client = new DynamoDB.DocumentClient(dynamoDBClientConfig);
}
// function
getData= async (id: string): Promise<any> => {
const response = await this.client
.query({
TableName: tableName,
IndexName: tableIndex,
KeyConditionExpression: 'id= :id',
ExpressionAttributeValues: {
':id': id
}
})
.promise();
return response;
}
}
My Test case
describe('DynamoDB', () => {
test('should return no data', async () => {
const spy = jest.spyOn(DynamoDBClient, 'getData').mockImplementation(() => jest.fn(() => {
return Promise.resolve({});
}));
const actual = await handler(event);
console.log(actual);
expect(actual).toEqual({ statusCode: 400, body: JSON.stringify({ }) });
});
});
CodePudding user response:
You defined .getData()
method using property initializer syntax. It will be bound to the class instance. Since the handler
function depends on DynamoDBClient
class via the import
statement, you can't create an instance in the test case and pass it to handler
when calling it.
You can mock aws-sdk
module and the DynamoDB.DocumentClient
class and its instance.
DynamoDBClient.ts
:
import { DynamoDB } from 'aws-sdk';
function getConfig() {
return { mockDynamoDBEndpoint: '' };
}
interface Config {
mockDynamoDBEndpoint: string;
}
export default class DynamoDBClient {
private config: Config;
private client: DynamoDB.DocumentClient;
constructor() {
this.config = getConfig();
const dynamoDBClientConfig = this.config.mockDynamoDBEndpoint
? {
endpoint: this.config.mockDynamoDBEndpoint,
sslEnabled: false,
region: 'local',
}
: undefined;
this.client = new DynamoDB.DocumentClient(dynamoDBClientConfig);
}
getData = async (id: string): Promise<any> => {
const response = await this.client
.query({
TableName: 'tableName',
IndexName: 'tableIndex',
KeyConditionExpression: 'id= :id',
ExpressionAttributeValues: {
':id': id,
},
})
.promise();
return response;
};
}
handler.ts
:
import DynamoDBClient from './DynamoDBClient';
interface APIGatewayProxyEvent {}
interface APIGatewayProxyResult {}
export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
let respData = await new DynamoDBClient().getData('123');
return { statusCode: 200, body: JSON.stringify(respData) };
};
handler.test.ts
:
import { handler } from './handler';
import { DynamoDB } from 'aws-sdk';
const mDocumentClientInstance = {
query: jest.fn().mockReturnThis(),
promise: jest.fn(),
};
jest.mock('aws-sdk', () => {
return {
DynamoDB: {
DocumentClient: jest.fn(() => mDocumentClientInstance),
},
};
});
describe('69475890', () => {
afterEach(() => {
jest.clearAllMocks();
});
test('should pass', async () => {
mDocumentClientInstance.promise.mockResolvedValueOnce({});
const event = {};
const actual = await handler(event);
expect(actual).toEqual({ statusCode: 200, body: JSON.stringify({}) });
expect(DynamoDB.DocumentClient).toBeCalled();
expect(mDocumentClientInstance.query).toBeCalledWith({
TableName: 'tableName',
IndexName: 'tableIndex',
KeyConditionExpression: 'id= :id',
ExpressionAttributeValues: {
':id': '123',
},
});
expect(mDocumentClientInstance.promise).toBeCalled();
});
});
test result:
PASS examples/69475890/handler.test.ts (8.642 s)
69475890
✓ should pass (4 ms)
-------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-------------------|---------|----------|---------|---------|-------------------
All files | 100 | 50 | 100 | 100 |
DynamoDBClient.ts | 100 | 50 | 100 | 100 | 18
handler.ts | 100 | 100 | 100 | 100 |
-------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 9.231 s