amazon-s3 - 如何在 mocha 中测试 aws S3
问题描述
这是我第一次尝试 Mocha/Chai 测试。使用 aws S3 在 mocha 中进行集成测试的最佳方法是什么。我尝试使用 aws-sdk-mock 和 sinon 来模拟 aws S3,但我真的不知道如何以及在哪里模拟这个?
这是我的代码:
// documentController
var aws = require('aws-sdk');
aws.config.update({
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
region: 'ap-southeast-1'
});
var s3 = new aws.S3({apiVersion: '2006-03-01'});
function deleteObject(key) {
s3.deleteObject({
'Bucket': 'delete-bucket',
'Key': key,
}, function(err, data) {
return
})
};
create: function(req, res) {
sails.async.auto(req, {
getDocumentContent: ['teamPrefDoc', 'getDocument', function (results, cb) {
var docKey = (
results.getDocument && results.getDocument.key
) ? results.getDocument.key : '';
var bucket = 'individual-docs';
if (!docKey || !bucket) {
return res.badRequest("Document doesn't have a key");
}
var params = {
Bucket: bucket,
Key: docKey
};
var tempDocStream = fs.createWriteStream(tempFileName + '.doc');
var s3Stream = s3.getObject(params).createReadStream();
s3Stream.pipe(tempDocStream).on('close', function() {
tempDocStream.close();
return cb(null, true);
}).on('error', function(err) {
sails.log(err);
return cb(null, false);
});
}],
'savePdfToS3': ['convertToPdfLocally', function (results, cb) {
if (!results.convertToPdfLocally) {
return cb(null, false)
}
var s3Key = results.documentDoc.key + '/pdf';
fs.readFile(tempFileName + '.pdf', (err, pdfBuffer) => {
if (err) { return cb(err); }
s3.putObject({
'Bucket': results.getDocumentContent,
'Key': s3Key,
'Body': pdfBuffer,
'ContentType': 'application/pdf'
}, function(err, data) {
if (err) { return cb(err); }
Documents.update({
id: id
}, {
pdf_key: s3Key
}).exec(function(err, updatedDocs) {
if (err) {
sails.log("Couldn't write pdf url to document", err);
return cb(err);
}
return cb(null, updatedDocs[0]);
});
})
});
}],
}
}
我有一个运行创建函数的 API,它运行一些数据库查询并将文档保存到 s3。所以,我想测试这个 API,但我不知道如何模拟 s3.getObject 和 s3.putObject。
这是我运行设置和拆卸连接的测试文件
// bootstrap.test.js
var sinon = require('sinon')
var AWSMock = require('aws-sdk-mock')
before(async () => {
const getObjectStub = AWS.S3.prototype.getObject = sinon.stub();
var s3 = new Aws.S3();
AWSMock.mock('S3', 'getObject', function(parmas,callback){
console.log("Callback received for getObject");
callback(null,'Success');
});
AWSMock.mock('S3', 'deleteObject', function(param,callback){
callback(null,{'s3deleteMarker': true
,'s3DeleteVersionId': 'VERSION ID'
,'s3DeletedImageSourceUid': 'SOURCE'
,'s3DeletedKey': 'KEY'});
});
这是我的测试代码:
// document.test.js
describe('document controller', () => {
it('should upload a doc', done => {
defaultDocument.resourceId = caseIds[0],
request(sails.hooks.http.app)
.post(`${apiVersion}/new/documents?app=test`)
.set('Authorization', `Bearer ${process.env.ACCESS_TOKEN}`)
.field(defaultDocument)
.attach('document0', 'some_pdf.pdf')
.expect(200)
.end((err, res)=> {
if(err) {
return done(err)
}
console.log(res.body)
done()
})
})
})
我对单元测试相当陌生,所以我很高兴你能指出我的任何方向:-)
非常感谢!
解决方案
关于 aws-sdk-mock 的关键点是“需要在被测试的函数内初始化 AWS 服务,以便模拟 SDK 方法”。
使用您正在使用的字典控制器样式很难知道这将如何工作(模拟工作可能有太多的魔力:
module.exports = {
login: function (req, res) { ... },
logout: function (req, res) { ... },
signup: function (req, res) { ... },
}
Sails 对您的代码结构非常固执己见,我认为您无法创建直接运行您的 api 的集成测试,无论您如何构建您的控制器,而无需大量黑客攻击。
Sails 文档建议将不依赖于请求、响应的代码移动到帮助函数中,例如deleteObject函数。对 getDocumentContent 的内容抽出类似的函数,放在一个单独的模块中。然后你仍然需要在每个辅助函数中实例化对象:
const s3 = new aws.S3();
我会做的是重写我的辅助函数,比如
function deleteObject(s3, key) {
s3.deleteObject...
}
通过这种方式,您可以传入任何您喜欢的内容并做出断言,以证明对 s3 对象的请求是在不同场景下按预期构建的。
我会编写我的集成测试以走上幸福的道路并写入实际的 s3 存储桶。
推荐阅读
- flutter - 焦点时如何更改 TextFiled 小部件背景颜色
- javascript - 当我通过浏览器发出请求时,Agora 云录制 api https://api.agora.io/v1/apps/:api_id/cloud_recording/acquire CORS 块
- python - 使用python在txt文件中查找字符串的最佳方法是什么?
- kotlin - 如何从 Kotlin 中的另一个类访问变量值?
- google-cloud-platform - 如何使用 GQL 查询以查找具有重复值的列/实体
- c++ - 在向量中查找大于 0(或一般 k)的最小元素的最佳方法是什么?
- php - 由于不活动,该页面已过期。请刷新并重试。“在我登录后在我的生产托管 cpanel 中”laravel 5.5
- php - 在 DataTable 服务器端处理中调用函数
- magento2 - Magento 2.3 Ubuntu 的 Venia 店面设置
- ruby-on-rails - Sidekiq 完成执行作业后,如何更新类实例的状态?