用于JavaScript jest单元测试的模拟机密管理器模块
我很难在jest单元测试中模拟AWS机密管理器模块。。。它出错的部分是.promise()。当我删除它时,代码对真正的机密管理器不起作用,所以我认为它需要留在那里。如何模拟getSecretData函数,以便getSecretData.promise()可以用于模拟 下面是SecretsManager.js代码:用于JavaScript jest单元测试的模拟机密管理器模块,javascript,amazon-web-services,unit-testing,jestjs,aws-secrets-manager,Javascript,Amazon Web Services,Unit Testing,Jestjs,Aws Secrets Manager,我很难在jest单元测试中模拟AWS机密管理器模块。。。它出错的部分是.promise()。当我删除它时,代码对真正的机密管理器不起作用,所以我认为它需要留在那里。如何模拟getSecretData函数,以便getSecretData.promise()可以用于模拟 下面是SecretsManager.js代码: import AWS from 'aws-sdk'; export class SecretsManager { constructor() { AWS.config.u
import AWS from 'aws-sdk';
export class SecretsManager {
constructor() {
AWS.config.update({
region: 'us-east-1',
});
this.secretsManager = new AWS.SecretsManager();
}
async getSecretData(secretName) {
try {
const response = await this.secretsManager.getSecretValue({
SecretId: secretName,
}).promise();
const secretString = response.SecretString;
const parsedSecret = JSON.parse(secretString);
return parsedSecret;
} catch (e) {
console.log('Failed to get data from AWS Secrets Manager.');
console.log(e);
throw new Error('Unable to retrieve data.');
}
}
}
下面是SecretsManager.test.js代码:
import { SecretsManager } from '../utils/SecretsManager';
jest.mock('aws-sdk', () => {
return {
config: {
update(val) {
},
},
SecretsManager: function () {
return {
async getSecretValue({
SecretId: secretName
}) {
return {
promise: function () {
return {
UserName: 'test',
Password: 'password',
};
}
};
}
};
}
}
});
describe('SecretsManager.js', () => {
describe('Given I have a valid secret name', () => {
describe('When I send a request for test_creds', () => {
it('Then the correct data is returned.', async () => {
const mockReturnValue = {
UserName: 'test',
Password: 'password',
};
const logger = getLogger();
const secretManager = new SecretsManager();
const result = await secretManager.getSecretData('test_creds');
expect(result).toEqual(mockReturnValue)
});
});
describe('When I send a request without data', () => {
it('Then an error is thrown.', async () => {
const secretManager = new SecretsManager();
await expect(secretManager.getSecretData()).rejects.toThrow();
});
});
});
});
这是我在运行测试时遇到的错误:
this.secretsManager.getSecretValue(...).promise is not a function
非常感谢您的任何建议或指点谢谢你看我的帖子。我终于让它工作了。。。我想这会在发帖后很快发生,但我不会删除帖子,而是会分享我是如何更改mock的,以使它在帮助其他人的情况下发挥作用的 注意:这只是更新的模拟,测试与上面的问题相同
// I added this because it's closer to how AWS returns data for real.
const mockSecretData = {
ARN: 'x',
Name: 'test_creds',
VersionId: 'x',
SecretString: '{"UserName":"test","Password":"password"}',
VersionStages: ['x'],
CreatedDate: 'x'
}
jest.mock('aws-sdk', () => {
return {
config: {
update(val) {
},
},
SecretsManager: function () {
return {
getSecretValue: function ( { SecretId } ) {
{
// Adding function above to getSecretValue: is what made the original ".promise() is not a function" error go away.
if (SecretId === 'test_creds') {
return {
promise: function () {
return mockSecretData;
}
};
} else {
throw new Error('mock error');
}
}
}
};
}
}});
我也遇到了这个问题。也许有一种更优雅的方法来处理这个问题,它还允许更好的控制和断言,但我还没有找到。请注意,in-test选项可以更好地与较新版本的Jest配合使用 我个人通过使用手动模拟和aws sdk的自定义模拟文件解决了这个问题。在您的情况下,它看起来如下所示:
# app_root/__tests__/__mocks__/aws-sdk.js
const exampleResponse = {
ARN: 'x',
Name: 'test_creds',
VersionId: 'x',
SecretString: '{"UserName":"test","Password":"password"}',
VersionStages: ['x'],
CreatedDate: 'x'
};
const mockPromise = jest.fn().mockResolvedValue(exampleResponse);
const getSecretValue = jest.fn().mockReturnValue({ promise: mockPromise });
function SecretsManager() { this.getSecretValue = getSecretValue };
const AWS = { SecretsManager };
module.exports = AWS;
然后在测试文件中:
// ... imports
jest.mock('aws-sdk');
// ... your tests
因此,简而言之:
- 不是直接在测试文件中进行模拟,而是将模拟控制权交给模拟文件,Jest知道如何在
目录中查找该文件\uuuuumocks\uuuu
- 您可以在模拟文件中为
创建模拟构造函数SecretsManager
使用mock函数返回一个实例SecretsManager
getSecretValue
返回模拟承诺getSecretValue
- 模拟承诺返回
示例响应
八达邦,八达邦 如果你投反对票,请留下一条评论,解释原因,以便我能理解问题所在。请你澄清是什么让新的解决方案起作用。我可以看到,在(旧版本和新版本)中,
getSecretValue()
函数返回一个带有promise
字段的对象,那么为什么它在旧版本中失败,但在新版本中通过呢?顺便问一下,是第一次考试还是第二次考试不及格?