Ich habe einen Endpunkt im API Gateway, der einer Lambda-Funktion in AWS zugeordnet ist. Wenn ich Testfälle für die neue Handlerfunktion des Endpunkts schreibe, möchte ich nicht, dass die spec-Datei die eigentliche API aufruft oder eine Verbindung zu DynamoDB herstellt. Ich habe versucht, sinon.stub
hinzuzufügen, aber es ruft immer noch „Connect to DynamoDB“ auf und der Testfall schlägt fehl. Ich kann nicht finden, wo der Stub schief geht.
handler.js:
saveUser(userName, logger) { const Item = { id: uuid.v4(), userName, ttl: parseInt(Date.now() / 1000) + 900 // expire the name after 15 minutes from now }; const params = { TableName: "my-table-name", Item }; logger.log(`Saving new user name to DynamoDB: ${JSON.stringify(params)}`); return new Promise(function(resolve, reject) { db.put(params, function(err, _) { if (err) { logger.exception(`Unable to connect to DynamoDB to create: ${err}`); reject({ statusCode: 404, err }); } else { logger.log(`Saved data to DynamoDB: ${JSON.stringify(Item)}`); resolve({ statusCode: 201, body: Item }); } }); }); }
Handler.spec.js:
import AWS from "aws-sdk"; const db = new AWS.DynamoDB.DocumentClient({ apiVersion: "2012-08-10" }); describe("user-name-handler", function() { const sandbox = sinon.createSandbox(); afterEach(() => sandbox.restore()); it("Test saveUser() method", async function(done) { const { saveUser } = userHandler; sandbox.stub(db, "put") .returns(new Promise((resolve, _) => resolve({ statusCode: 200 }))); try { const result = await saveUser("Sample User", { log: () => {}, exception: () => {} }); expect(result).to.be.equal({ data: "some data" }); done(); } catch (err) { console.log(err); done(); } }); });
Fehler:
Error: Resolution method is overspecified. Specify a callback *or* return a Promise; not both.
Ich habe das err
-Objekt über die Konsole protokolliert und es hat mir diesen Fehler angezeigt, der mich vermuten lässt, dass es versucht, eine Verbindung zu DynamoDB herzustellen.
Error: connect ENETUNREACH 127.0.0.1:80 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1144:16) { message: 'Missing credentials in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1', errno: 'ENETUNREACH', code: 'CredentialsError', syscall: 'connect', address: '127.0.0.1', port: 80, time: 2023-05-07T10:45:25.835Z, originalError: { message: 'Could not load credentials from any providers', errno: 'ENETUNREACH', code: 'CredentialsError', syscall: 'connect', address: '127.0.0.1', port: 80, time: 2023-05-07T10:45:25.835Z, originalError: [Object] }
Verwandt: So testen Sie Methoden, die Daten von AWS DynamoDB zurückgeben
您正在嘲笑测试文件中声明的
db
- 而不是saveUser
实际使用的db
。解决方案是将 db 声明移至其自己的模块,例如:db.js
然后从
saveUser
模块和测试中导入它 - 这样我们就可以模拟saveUser
使用的同一个db
实例。更新
我能够使用以下代码成功运行测试:
测试代码:
用户处理程序文件:
package.json
输出
在文件中分离数据库连接
我们可以将数据库连接分离到不同的文件中,并将其导入到处理程序实现以及 spec 文件中。
db.js
yields()
函数存根不应直接返回
Promise
,而应与.yields()
及其回调将接受的参数链接。我们可以更改参数以覆盖代码的各个分支。代码
有用的链接
https://www.youtube.com/watch?v=vXDbmrh0xDQ