函数中模拟对S3的调用"/>
使用笑话在AWS Lambda函数中模拟对S3的调用
[我正在尝试使用Jest在本地Node.JS AWS Lambda函数中模拟对putObject的调用,但由于某些原因,我的期望值一直保持为0。
这是我的主要功能(index.js):
const S3 = require("aws-sdk/clients/s3");
const s3 = new S3();
exports.handler = async (event) => {
putFunction = async (params, callback) => {
await s3.putObject(params, callback).promise();
};
const params = {
Bucket: "some value",
Key: "some key value",
ContentType: "application/json",
Body: "some body value",
};
const callback = {
function(err, data) {
console.log(JSON.stringify(err) + " " + JSON.stringify(data));
},
};
putFunction(params, callback);
}
我曾尝试将异步添加到我的测试函数中,因为我认为这是一个异步问题,但似乎仍然收到相同的错误。这是我的测试代码(index.test.js):
let myHandler = require("../../src/lambda/index");
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 params = {
Bucket: "test1",
Key: "test2",
ContentType: "application/json",
Body: "test3",
};
const callback = {
function(err, data) {
console.log(JSON.stringify(err) + " " + JSON.stringify(data));
},
};
const putFunc = myHandler.handler.putFunction;
putFunc;
expect(mockedPutObject).toHaveBeenCalledWith(params, callback);
});
任何帮助都会很棒。
回答如下:这是一个Jest / Node专用答案,适用于那些不想引入任何第三方模拟库(例如aws-sdk-mock。
问题(您的答案中没有看到错误本身)很可能与实现代码中的.promise()
相关。
您已在实现中添加了此内容,以告知SDK对所调用的任何操作均向您返回承诺。
await s3.putObject(params, callback).promise();
返回的诺言将要么拒绝,要么出错,或者使用数据解决。
这意味着在基于承诺的方法中,您可以完全省略回调
。await s3.putObject(params).promise();
(从this AWS blog post中获取)
修复处理程序...
您可以:
将回调逻辑放在后续的promise链块中:.then((data) => {
// ... do stuff
})
.catch((err) => {
// ... handle error
}
.then((data) => {
// ... do stuff
})
.catch((err) => {
// ... handle error
}
或更妙的是(看起来您已经在拥抱)更现代的ES6方法]
在try-catch块中等待putObject承诺:try {
const data = await s3.putObject(params).promise()
// ... do things with data on successful response
} catch (err) {
// ... handle error
}
try {
const data = await s3.putObject(params).promise()
// ... do things with data on successful response
} catch (err) {
// ... handle error
}
将它们放在一起
您的处理程序应如下所示:
const { S3 } = require("aws-sdk"); const s3 = new S3(); exports.handler = async (event) => { const params = { Bucket: "some value", Key: "some key value", ContentType: "application/json", Body: "some body value", }; try { const data = await s3.putObject(params).promise(); // ... do stuff with data return { statusCode: 200, body: JSON.stringify(data), // ... etc. } } catch (err) { // ... handle error return { statusCode: 400, // or any 4XX, 5XX body: '...', // whatever you wish to return on error // ... etc. } } }
修复测试...
请记住,您可以省略回调,测试代码需要在处理程序中.promise()
的调用链中反映出额外的putObject
。
在测试文件中,SDK模拟需要配置为:a)返回顶级S3
构造函数b)让此S3
构造函数本身返回一个包含putObject
函数的对象c)让此putObject
本身返回一个包含promise
函数的对象
以便可以像真正的SDK那样调用它:
模拟设置,以防止发生const { S3 } = require("aws-sdk"); // require("aws-sdk") returns { S3 } const s3 = new S3() // returns { putObject } await s3.putObject(params) // returns { promise } .promise(); // returns ...your_mock_response
// You need to return the { promise } here even if you don't care about // mock calls beyond the putObject, because the handler itself calls .promise() // and will throw "TypeError: Cannot read property 'promise' of undefined" const putObjectMock = jest.fn(() => ({ promise: jest.fn() })); jest.mock('aws-sdk', () => ({ S3: jest.fn(() => ({ putObject: putObjectMock, })), })); // S3 must have jest.fn(...) over an ordinary function otherwise // the new S3() in the handler will fail. // Jest does its magic with the function you provide to make it callable as a constructor const myHandler = require("../../src/lambda/index"); // Don't forget to add the "async" before the "it" callback as your handler is async it("has to mock s3#putObject", async () => { const params = { Bucket: "test1", Key: "test2", ContentType: "application/json", Body: "test3", }; await handler(); // Call the handler to then assert against the mock params expect(putObjectMock).toHaveBeenCalledWith(params); });
最后说明-添加处理程序导入之后
"Cannot access 'putObject' before initialization"
错误(由处理程序对SDK的要求引起)。希望这会有所帮助!
更多推荐
使用笑话在AWS Lambda函数中模拟对S3的调用
发布评论