【问题标题】:Mock the constructor for AWS.DynamoDB.DocumentClient using jest使用 jest 模拟 AWS.DynamoDB.DocumentClient 的构造函数
【发布时间】:2020-01-08 16:36:56
【问题描述】:

我有一个看起来像这样的函数:

function connect() {
   const secret = 'secret';
   const key = 'key';
   const region = 'region';
   const client = new AWS.DynamoDB({
      secret,
      key,
      region
   });'
   return new AWS.DynamoDB.DocumentClient({ service: client })
}

我想测试函数connect。我已经像这样模拟了 DynamoDB 构造函数:

// See https://stackoverflow.com/questions/47606545/mock-a-dependencys-constructor-jest
jest.mock('aws-sdk', () => {
  const DynamoDB = jest.fn().mockImplementation(() => {
    return {};
  });
  return {
    DynamoDB,
  };
});

但是,这意味着DocumentClient 构造函数失败。我该如何模拟呢?

【问题讨论】:

    标签: typescript amazon-dynamodb jestjs aws-sdk-nodejs ts-jest


    【解决方案1】:

    Jest 为运行测试提供 DynamoDB 集成。看this document,看3. Configure DynamoDB client

    const {DocumentClient} = require('aws-sdk/clients/dynamodb');
    
    const isTest = process.env.JEST_WORKER_ID;
    const config = {
      convertEmptyValues: true,
      ...(isTest && {endpoint: 'localhost:8000', sslEnabled: false, region: 'local-env'})
    };
    
    const ddb = new DocumentClient(config);
    

    我猜你可以将 DynamoDB 客户端配置抽象出来(如果你还没有)到它自己的模块文件中并导出该客户端,以便在其他地方需要它,当 Jest 测试运行时,客户端被配置为指向您按照 Jest DynamoDB 文档的其他步骤设置的模拟 DynamoDB 服务器/表。

    【讨论】:

    • 很高兴知道我们不必编写自己的帮助程序来运行集成测试(就像我一直在做的那样),我宁愿不使用本地发电机服务器单元测试。我认为如果使用 ts-jest,我们可以只使用 jest.mock('aws-sdk') 因为 aws-sdk 现在附带打字稿定义。
    【解决方案2】:

    基于上述 duxtinto 的评论:

    在我的情况下(如果我没看错的话,在 OP 的情况下),DynamoDB 不是作为函数调用的,而是一个带有 DocumentClient 字段的对象,所以这对我有用:

    jest.mock('aws-sdk', () => {
      return {
        DynamoDB: { // just an object, not a function
          DocumentClient: jest.fn(() => ({
            put: mockDynamoDbPut
          }))
        }
      }});
    

    【讨论】:

      【解决方案3】:

      在 TypeScript 中使用 jest 对我有用的方法:

      // blabla.test.ts
      import { DynamoDB } from 'aws-sdk';
      import { ConsumerClass } from '../consumer-class';
      import { DependencyConsumerClass } from '../dependency-consumer-class';
      
      /*
      * Inside consumerClassInstance.save() is calling this.dynamo.putItem({...}).promise();
      */
      jest.mock('aws-sdk', () => {
          return {
              DynamoDB: jest.fn(() => {
                  return {
                      putItem: jest.fn(() => {
                          return {
                              promise: jest.fn(() => true)
                          };
                      })
                  };
              })
          };
      });
      
      test('sample test', async () => {
          const dependencyConsumerClass = new DependencyConsumerClass();
          const consumerClassInstance = new ConsumerClass(dependencyConsumerClass, new DynamoDB());
          
          const result = await consumerClassInstance.save();
          console.log(result);
      });
      

      【讨论】:

        【解决方案4】:

        这对我有用:

        const mockDynamoDbPut = jest.fn().mockImplementation(() => {
          return {
            promise() {
              return Promise.resolve({});
            }
          };
        });
        
        jest.doMock('aws-sdk', () => {
          return {
            DynamoDB: jest.fn(() => ({
              DocumentClient: jest.fn(() => ({
                put: mockDynamoDbPut
              }))
            }))
          };
        });
        

        希望对你也有帮助。

        问候,

        大卫。

        【讨论】:

        • 这给了我错误ConfigError: Missing region in config。任何想法将不胜感激!
        • 当这种情况发生在我身上时,通常与模拟无法以某种方式或在错误的位置工作有关。这意味着 DocumentClient 尝试连接到数据库实例。
        • 在我的情况下(如果我没看错的话,在 OP 的情况下),DynamoDB 不是作为函数调用的,而是一个带有 DocumentClient 字段的对象,所以这对我有用:` jest.mock('aws-sdk', () => { return { DynamoDB: { // 只是一个对象,而不是一个函数 DocumentClient: jest.fn(() => ({ put:模拟DynamoDbPut })) } }}); `
        【解决方案5】:

        DocumentClient 可能会调用一些client 方法,因此只需定义这些方法存根即可。例如,DocumentClient 将在您的代码中使用 batchGetItem

        import AWS from 'aws-sdk';
        
        jest.mock('aws-sdk', () => {
          const DynamoDB = jest.fn().mockImplementation(() => {
            return {
              batchGetItem: jest.fn(),
            };
          });
          return {
            DynamoDB,
          };
        });
        
        // you could inspect the mock
        console.log(new AWS.DynamoDB({ ... }));
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-05-06
          • 2021-04-05
          • 1970-01-01
          • 2019-08-19
          • 2023-03-09
          • 2019-08-06
          • 1970-01-01
          • 2011-02-27
          相关资源
          最近更新 更多