使用jest模拟aws-sdk S3#putObject实例方法

vam*_*olu 6 mocking amazon-s3 node.js jestjs aws-sdk-nodejs

对于包含以下内容的源代码

 const S3 = require('aws-sdk/s3/clients')
 const s3 = new S3()
 s3.putObject(params, callback)
Run Code Online (Sandbox Code Playgroud)

我基于这篇文章添加了以下模拟:

 jest.mock('aws-sdk/s3/clients')
 const S3 = require('aws-sdk/s3/clients')

 it('has to mock S3#putObject', () => { 
    S3.prototype.putObject.mockImplementation(() => cb()) 
 })
Run Code Online (Sandbox Code Playgroud)

但我无法找到S3.prototype.putObject有/无嘲弄,因为api似乎在这里apiLoader模式中构建不同.但是,这里的定义似乎完全不同

我也尝试过:

  const AWS = require('aws-sdk')
  console.log(AWS.S3.prototype.putObject) // undefined
Run Code Online (Sandbox Code Playgroud)

如果我在原型上找不到它,我怎么能模拟一个方法呢?

在承诺中包装打破了结果

我已将源代码包装在Promise中,如下所示:

new Promise((resolve, reject) => {
    s3.putObject(params, (err, data) => {
        if (err) {
            reject(err)
        } else {
           resolve(data)
       }
    })
})
Run Code Online (Sandbox Code Playgroud)

并使用如下所示的测试:

const mockedPutObject = jest.fn();
jest.mock('aws-sdk/s3/clients', () => {
  return class S3 {
    putObject(params, cb) {
      mockedPutObject(params, cb);
    }
  }
});

it('should call aws S3.putObject method', async () => {
  const data = {
    Bucket: 'aaa',
    Key: 'bbb',
    Content: 'this can be anything',
    ACL: 'public-read'
  }
  await putObject(data)
  console.log(mockFn.calls)
  expect(mockFn).toBeCalledWith(data)
})
Run Code Online (Sandbox Code Playgroud)

导致错误的putObject> with params>应该调用aws S3.putObject方法

Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.
Run Code Online (Sandbox Code Playgroud)

我认为将调用代码包装在手动承诺中或使用如下的库:

const {promisify} = require('es6-promisify')
const putS3Object = promisify(s3.putObject.bind(s3))
return putS3Object(data)
Run Code Online (Sandbox Code Playgroud)

同样也失败了.

tru*_*nga 7

对于源代码

//src.js
const S3 = require('aws-sdk/clients/s3');
const s3 = new S3();

const putFunction = () => {
  s3.putObject(params, callback);
}
export default putFunction;
Run Code Online (Sandbox Code Playgroud)

以下方法可用于模拟S3客户端的putObject方法.

const mockedPutObject = jest.fn();
jest.mock('aws-sdk/clients/s3', () => {
  return class S3 {
    putObject(params, cb) {
      mockedPutObject(params, cb);
    }
  }
});

it('has to mock S3#putObject', () => {
    const putFunc = require('./src).default.putFunc;
    putFunc();
    expect(mockedPutObject).toHaveBeenCalledWith(params, callback);
 })
Run Code Online (Sandbox Code Playgroud)

  • 所以我在 `const S3 = new AWS.S3();` 上得到了 `TypeError: AWS.S3 is not a constructor` ,这个模拟就位。 (4认同)
  • 正确的模块路径是“ aws-sdk / clients / s3”。 (2认同)