TypeError: this.dynamodb.batchGetItem is not a function with jest

TypeError: this.dynamodb.batchGetItem is not a function with jest

我正在尝试创建一个简单的 class 包装 Amazon SDK for dynamodb。测试时,出现错误:

TypeError: this.dynamodb.batchGetItem is not a function

这是我的测试用例:test.js

import DynamoDBContentAccess from "../../../src/api/dynamodb_content_access";
const AWS = require("aws-sdk");
describe("services", () => {
  it("returns a list of services", async () => {
    let serviceInterface = new DynamoDBContentAccess();
    const params = {
      bearerToken: "fake bearer token",
      filter: {},
      skip: 10,
      limit: 10,
    };
    const mockResponse = {
      Responses: {
        Services: [
          {
            ServiceId: {
              S: "example1",
            },
          },
        ],
      },
    }
    const batchGetItemPromise = jest.fn().mockReturnValue({
      promise: jest.fn().mockResolvedValue(mockResponse),
    });
    serviceInterface.dynamodb = jest.fn().mockImplementation(() => { return {
      batchGetItem: batchGetItemPromise,
    }});
    const result = await serviceInterface.findServices(params);
    expect(result).toEqual(mockResponse);
  });
});

这是正在测试的class:dynamodb_content_access.js

import ContentAccess from "./content_access"
const AWS = require("aws-sdk");
class DynamoDBContentAccess {
  constructor() {
   this.dynamodb = new AWS.DynamoDB();
  }
  async findServices (bearerToken, filter, skip, limit) {
    const params = {
      TableName: 'Services',
    };
    const results = await this.dynamodb.batchGetItem(params).promise();
    return results
    }
 }
 export default DynamoDBContentAccess;

我的 mock 级别不对吗?我错过了什么?

您可以使用 jest.spyOn(object, methodName) 模拟 AWS.DynamoDB class 及其实例。

使用mockFn.mockReturnThis()模拟方法链调用。

例如

dynamodb_content_access.js:

const AWS = require('aws-sdk');

class DynamoDBContentAccess {
  constructor() {
    this.dynamodb = new AWS.DynamoDB();
  }
  async findServices(bearerToken, filter, skip, limit) {
    const params = {
      TableName: 'Services',
    };
    const results = await this.dynamodb.batchGetItem(params).promise();
    return results;
  }
}

export default DynamoDBContentAccess;

dynamodb_content_access.test.js:

import DynamoDBContentAccess from './dynamodb_content_access';

const AWS = require('aws-sdk');

describe('services', () => {
  it('returns a list of services', async () => {
    const params = {
      bearerToken: 'fake bearer token',
      filter: {},
      skip: 10,
      limit: 10,
    };
    const mockResponse = {
      Responses: {
        Services: [
          {
            ServiceId: {
              S: 'example1',
            },
          },
        ],
      },
    };

    const dynamodb = {
      batchGetItem: jest.fn().mockReturnThis(),
      promise: jest.fn().mockResolvedValueOnce(mockResponse),
    };
    const DynamoDBSpy = jest.spyOn(AWS, 'DynamoDB').mockImplementation(() => dynamodb);
    let serviceInterface = new DynamoDBContentAccess();

    const result = await serviceInterface.findServices(params);
    expect(result).toEqual(mockResponse);
    expect(DynamoDBSpy).toBeCalledTimes(1);
    expect(dynamodb.batchGetItem).toBeCalledWith({ TableName: 'Services' });
    expect(dynamodb.promise).toBeCalledTimes(1);
  });
});

单元测试结果:

 PASS  examples/66858621/dynamodb_content_access.test.js (7.959 s)
  services
    ✓ returns a list of services (3 ms)

----------------------------|---------|----------|---------|---------|-------------------
File                        | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------------------------|---------|----------|---------|---------|-------------------
All files                   |     100 |      100 |     100 |     100 |                   
 dynamodb_content_access.js |     100 |      100 |     100 |     100 |                   
----------------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        8.846 s, estimated 10 s