如何用玩笑模拟 dynamoDB 调用?

kam*_*bar 5 testing unit-testing amazon-dynamodb typescript jestjs

我有一个简单的处理程序,调用 getData 在单独的文件中定义

export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
  let respData = await new DynamoDBClient().getData(123);
  return {
    statusCode: 200,
    body: JSON.stringify(respData),
  };
};
Run Code Online (Sandbox Code Playgroud)

在我的 DynamoDB 课程中,我有以下内容。

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;
}
}
Run Code Online (Sandbox Code Playgroud)

我的测试用例

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({ }) });
  });
 });
Run Code Online (Sandbox Code Playgroud)

sli*_*wp2 2

.getData()使用属性初始值设定项语法定义了方法。它将绑定到类实例。由于该handler函数通过语句依赖于DynamoDBClientimport,因此您无法在测试用例中创建实例并handler在调用它时将其传递给它。

\n

您可以模拟aws-sdk模块和DynamoDB.DocumentClient类及其实例。

\n

DynamoDBClient.ts

\n
import { DynamoDB } from 'aws-sdk';\n\nfunction getConfig() {\n  return { mockDynamoDBEndpoint: '' };\n}\ninterface Config {\n  mockDynamoDBEndpoint: string;\n}\n\nexport default class DynamoDBClient {\n  private config: Config;\n  private client: DynamoDB.DocumentClient;\n\n  constructor() {\n    this.config = getConfig();\n\n    const dynamoDBClientConfig = this.config.mockDynamoDBEndpoint\n      ? {\n          endpoint: this.config.mockDynamoDBEndpoint,\n          sslEnabled: false,\n          region: 'local',\n        }\n      : undefined;\n\n    this.client = new DynamoDB.DocumentClient(dynamoDBClientConfig);\n  }\n\n  getData = async (id: string): Promise<any> => {\n    const response = await this.client\n      .query({\n        TableName: 'tableName',\n        IndexName: 'tableIndex',\n        KeyConditionExpression: 'id= :id',\n        ExpressionAttributeValues: {\n          ':id': id,\n        },\n      })\n      .promise();\n    return response;\n  };\n}\n
Run Code Online (Sandbox Code Playgroud)\n

handler.ts

\n
import DynamoDBClient from './DynamoDBClient';\n\ninterface APIGatewayProxyEvent {}\ninterface APIGatewayProxyResult {}\n\nexport const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {\n  let respData = await new DynamoDBClient().getData('123');\n  return { statusCode: 200, body: JSON.stringify(respData) };\n};\n
Run Code Online (Sandbox Code Playgroud)\n

handler.test.ts

\n
import { handler } from './handler';\nimport { DynamoDB } from 'aws-sdk';\n\nconst mDocumentClientInstance = {\n  query: jest.fn().mockReturnThis(),\n  promise: jest.fn(),\n};\njest.mock('aws-sdk', () => {\n  return {\n    DynamoDB: {\n      DocumentClient: jest.fn(() => mDocumentClientInstance),\n    },\n  };\n});\n\ndescribe('69475890', () => {\n  afterEach(() => {\n    jest.clearAllMocks();\n  });\n  test('should pass', async () => {\n    mDocumentClientInstance.promise.mockResolvedValueOnce({});\n    const event = {};\n    const actual = await handler(event);\n    expect(actual).toEqual({ statusCode: 200, body: JSON.stringify({}) });\n    expect(DynamoDB.DocumentClient).toBeCalled();\n    expect(mDocumentClientInstance.query).toBeCalledWith({\n      TableName: 'tableName',\n      IndexName: 'tableIndex',\n      KeyConditionExpression: 'id= :id',\n      ExpressionAttributeValues: {\n        ':id': '123',\n      },\n    });\n    expect(mDocumentClientInstance.promise).toBeCalled();\n  });\n});\n
Run Code Online (Sandbox Code Playgroud)\n

测试结果:

\n
 PASS  examples/69475890/handler.test.ts (8.642 s)\n  69475890\n    \xe2\x9c\x93 should pass (4 ms)\n\n-------------------|---------|----------|---------|---------|-------------------\nFile               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s \n-------------------|---------|----------|---------|---------|-------------------\nAll files          |     100 |       50 |     100 |     100 |                   \n DynamoDBClient.ts |     100 |       50 |     100 |     100 | 18                \n handler.ts        |     100 |      100 |     100 |     100 |                   \n-------------------|---------|----------|---------|---------|-------------------\nTest Suites: 1 passed, 1 total\nTests:       1 passed, 1 total\nSnapshots:   0 total\nTime:        9.231 s\n
Run Code Online (Sandbox Code Playgroud)\n