模拟 'aws-sdk' 的 'S3' 特性(nodeJS 和 Jest)

Mock 'S3' feature of 'aws-sdk' (nodeJS and Jest)

我需要测试一个文件,该文件负责通过 'aws-sdk' (nodeJs + Jest) 从 S3 检索数据。文件是:

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

let S3 = null;

const getS3 = async () => {
  if (S3 === null) {
    const config = {
      endpoint: new AWS.Endpoint(process.env.S3_URL),
      s3ForcePathStyle: true,
    };
    S3 = new AWS.S3(config);
  }
  return S3;
};

module.exports.getObjectList = async (prefix) => {
  const params = {
    Bucket: process.env.S3_BUCKET,
    Delimiter: '/',
    Prefix: prefix,
  };
  const s3 = await getS3();
  const objectList = s3
    .listObjects(params)
    .promise()
    .then((data) => {
      const keys = data.Contents.map((c) => c.Key);
      return keys;
    })
    .catch((err) => {
      console.error(err);
      return null;
    });
  return objectList;
};


测试文件如下:

const s3Client = require('./s3Client');

const mockS3Instance = {
  listObjects: jest.fn().mockReturnThis(),
  promise: jest.fn().mockReturnThis(),
  catch: jest.fn(),
};

jest.mock('aws-sdk', () => {
  return {
    S3: jest.fn(() => mockS3Instance),
    Endpoint: jest.fn(() => {
      'blabla';
    }),
  };
});

describe('s3Client tests', () => {
  it('basic test', async () => {
    const getObjectListResult = await s3Client.getObjectList('test');
    expect(1).toBe(1);
  });
});

但是返回错误信息:

ypeError: s3.listObjects(...).promise(...).then is not a function

您需要在 mockS3Instance 对象中添加一个 then 模拟

感谢@gear4 的回复,我得以修复我的代码: (主要部分是关于从 mock 返回的 promise)

const s3Client = require('./s3Client');

const mockS3Instance = {
  listObjects: jest.fn().mockReturnThis(),
  promise: jest.fn(() => {
    return new Promise((resolve, reject) => {
      return resolve({
        Contents: [{ Key: 'test-file-1' }, { Key: 'test-file-2' }],
      });
    });
  }),
  catch: jest.fn(),
};

jest.mock('aws-sdk', () => {
  return {
    S3: jest.fn(() => mockS3Instance),
    Endpoint: jest.fn(() => {
      'blabla';
    }),
  };
});

describe('s3Client tests', () => {
  it('Dummy tests: to be implemented', async () => {
    const getObjectListResult = await s3Client.getObjectList('test');
    expect(JSON.stringify(getObjectListResult)).toBe(
      JSON.stringify(['test-file-1', 'test-file-2']),
    );
  });
});