以下を含むソースコードの場合:
const S3 = require('aws-sdk/s3/clients')
const s3 = new S3()
s3.putObject(params, callback)
この記事 に基づいて次のモックを追加しました:
jest.mock('aws-sdk/s3/clients')
const S3 = require('aws-sdk/s3/clients')
it('has to mock S3#putObject', () => {
S3.prototype.putObject.mockImplementation(() => cb())
})
しかし、apiLoader
パターン here の間にAPIが異なる方法で構築されているように見えるので、モックなしでS3.prototype.putObject
を見つけることができません。ただし、定義は完全に異なるようです here
私も試しました:
const AWS = require('aws-sdk')
console.log(AWS.S3.prototype.putObject) // undefined
プロトタイプでメソッドが見つからない場合、どうすればメソッドをモックできますか?
Promiseでラップすると結果が壊れます
私はソースコードを次のようなPromiseでラップしました:
new Promise((resolve, reject) => {
s3.putObject(params, (err, data) => {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
次のようなテストを使用します。
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)
})
これによりエラーputObjectが発生します›適切なパラメータを使用して› aws S3.putObjectメソッドを呼び出す必要があります
Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.
呼び出しコードを手作業のプロミスでラップするか、次のようなライブラリを使用すると思います。
const {promisify} = require('es6-promisify')
const putS3Object = promisify(s3.putObject.bind(s3))
return putS3Object(data)
同様に失敗します。
ソースコードについて
//src.js
const S3 = require('aws-sdk/clients/s3');
const s3 = new S3();
const putFunction = () => {
s3.putObject(params, callback);
}
export default putFunction;
以下のアプローチを使用して、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);
})
jest.fn().mockImplementation
を使用できます
// index.js
const AWS = require('aws-sdk')
const s3 = new AWS.S3()
s3.putObject({},()=> {
return 2;
});
// your test under test folder
let AWS = require('aws-sdk');
describe('test', () => {
let result;
beforeEach(()=>{
AWS.S3 = jest.fn().mockImplementation( ()=> {
return {
putObject (params, cb) {
result = cb();
}
};
});
require('../index');
});
test('call s3', () => {
expect(result).toBe(2);
});
});
テスト目的でAWS.S3のプロトタイプメソッドでオブジェクトを再作成したくない場合は、次のコードを追加するだけで実装をモックできます。
// Arrange
const spy = jest.fn();
S3.prototype.getObject = spy;
// Act
...
//Assert
expect(spy).toHaveBeenCalledWith(data);
それがどう進んだかを知らせてください(これは遅くなるかもしれませんが)