我怎么能开玩笑嘲笑aws-sdk



我正试图用笑话来嘲笑aws-sdk。实际上我只关心一个功能。我该怎么做?我读过关于用笑话嘲笑类的文档,但这些文档很复杂,我不太理解。

这是我最好的尝试:

handler.test.js

'use strict';
const aws = require('aws-sdk');
const { handler } = require('../../src/rotateSecret/index');
jest.mock('aws-sdk');
const event = {
SecretId: 'test',
ClientRequestToken: 'ccc',
Step: 'createSecret',
};
describe('rotateSecret', () => {
it.only('should not get or put a secret', async () => {
aws.SecretsManager.mockImplementation(() => ({
getSecretValue: () => ({}),
}));
expect.assertions(1);
await handler(event);
// You can see what I am trying to do here but it doesn't work
expect(aws.SecretsManager.getSecretManager).not.toHaveBeenCalled();
});
});

handler.js

exports.handler = async (event) => {
const secretsManager = new aws.SecretsManager();
const secret = await secretsManager.describeSecret({ SecretId: event.SecretId }).promise();
if (someCondition) {
console.log("All conditions not met");
return;
}
return secretsManager.getSecretValue(someParams)
};

好的,所以我的方法如下:

AWS-SDK模型


aws-sdk创建一个实际的mock,并将其放在项目根目录的__mocks__/aws-sdk.js文件中

// __mocks__/aws-sdk.js
class AWS {
static SecretsManager = class {
describeSecret = jest.fn(() =>{
return { promise: ()=> Promise.resolve({ ARN: "custom-arn1", Name: "describeSec" })}
});
getSecretValue = jest.fn(() =>{
return {promise: ()=> Promise.resolve({ ARN: "custom-arn2", Name: "getSecretVal" })
});
};
}
module.exports = AWS;

我在SecretsManager之前使用过static,因为AWS类从未实例化,但它希望访问SecretsManager类。

SecretsManager中,我定义了2个函数,并使用jest.fn对它们进行了存根处理。

现在和你在测试文件中做的一样:

jest.mock('aws-sdk');

如何测试


要测试是否调用了mock函数,这是一个棘手的部分(所以我将在本文末尾详细介绍(。

更好的方法是在所有处理完成后对主函数的最终结果进行断言。

断言


回到您的测试文件中,我会简单地用await调用处理程序(正如您已经拥有的那样(,然后对最终结果断言,如下所示:

// test.js
describe("rotateSecret", () => {
it.only("should not get or put a secret", async () => {
const event = {name:"event"};
const result = await handler(event);
expect(result).toEqual("whatever-your-function-is-expected-to-return");
});
});

测试Secret Manager的函数调用


为此,您需要调整主handler.js文件本身,并需要从主功能体中取出invocation of secrets Manager,如下所示:

const secretsManager = new aws.SecretsManager(); // <---- Declare it in outer scope
exports.handler = async (event) => {
const secret = await secretsManager
.describeSecret({ SecretId: event.SecretId })
.promise();
if (someCondition) {
console.log("All conditions not met");
return;
}
return secretsManager.getSecretValue(someParams);
};

然后回到test.js文件中,在启动处理程序函数之前,您需要类似地声明SecretsManager调用,如下所示:

//test.js
describe("rotateSecret", () => {
const secretsManager = new aws.SecretsManager(); // <---- Declare it in outer scope
it.only("should not get or put a secret", async () => {
const event = {name:"event"};
await handler(event);
// Now you can make assertions on function invocations
expect(secretsManager.describeSecret).toHaveBeenCalled();
// OR check if passed args were correct
expect(secretsManager.describeSecret).toHaveBeenCalledWith({
SecretId: event.SecretId,
});
});
});

这将允许您对函数调用以及传递的参数进行断言。

我在函数范围之外声明它的原因是告诉JestsecretsManager应该存在于全局范围中的某个地方,并且应该从那里使用它。

以前,我们在函数范围内声明了它,所以Jest会调用它,但我们无法访问它。

我们不能像AWS.SecretsManager.getSecretManager那样直接引用它,因为getSecretManager方法只有在实例化SecretsManager类之后才可用(即使这样做,也会得到该类的新实例,这对任何断言都没有帮助(。

__mocks_/aws.js伪模块的下侧


显而易见的问题是,您在每次调用中都会截断函数,也许您不希望这样。

也许你只想在特定的测试中截取一次,但对于其他测试,你希望它正常运行。

在这种情况下,不应该创建__mocks__文件夹。

相反,创建一个一次性的假调用,但要确保SecretsManager调用像以前一样在测试文件的外部范围内。

//test.js
const aws = require("aws-sdk");
describe("rotateSecret", () => {
// Declare it in outer scope
const secretsManager = new aws.SecretsManager();
it.only("should not get or put a secret", async () => {
const event = {name:"event"};
// Create a mock for this instance ONLY
secretsManager.describeSecret = jest.fn().mockImplementationOnce(()=>Promise.resolve("fake-values"));
await handler(event);
expect(secretsManager.describeSecret).toHaveBeenCalled();
expect(secretsManager.describeSecret).toHaveBeenCalledWith({
SecretId: event.SecretId,
});
});
});

最新更新