【发布时间】:2021-11-06 00:14:10
【问题描述】:
我正在尝试模拟一个模块,这里是来自 aws-sdk 的 S3。
我让它工作的唯一方法就是这样:
jest.mock('aws-sdk', () => {
return {
S3: () => ({
putObject: jest.fn()
})
};
});
问题在于我无法访问 S3 或 putObject 作为模拟变量,我可以检查是否出于测试目的调用。
所以我想做这样的事情:
const putObject = jest.fn();
jest.mock('aws-sdk', () => {
return { S3: () => ({ putObject }) };
});
我总是对其他模块这样做,它运行良好,它甚至适用于 lambda,但不适用于这种情况。
对我来说,这两个代码看起来完全一样,所以我真的不明白发生了什么以及为什么它的工作方式不完全相同。
当我在要测试的代码中控制台记录 s3 时,我明白了:
{ putObject: undefined }
另外,我使用 TypeScript,所以我不能只导入测试文件中的模块,如果它不是模拟变量,我就不能模拟返回值。
感谢您的帮助!
编辑:
这是一个可重现的最小问题示例:
上传文件.ts
import AWS from 'aws-sdk';
const s3 = new AWS.S3();
export const uploadFile = async (key, body) => {
try {
await s3
.putObject({
Bucket: 'myBucket',
Key: key,
Body: body,
})
.promise();
} catch (error) {
console.log(error);
}
};
上传文件.test.ts
import { uploadFile } from './uploadFile';
const mockPutObject = jest.fn(() => ({ promise: jest.fn() }));
jest.mock('aws-sdk', () => {
return { S3: () => ({ putObject: mockPutObject }) };
});
describe('Test uploadFile', () => {
it('should call putObject', () => {
uploadFile('key', { test: 'test' });
expect(mockPutObject).toHaveBeenCalled();
});
});
【问题讨论】:
-
您可以尝试将
putObject重命名为mockPutObject。开玩笑有一种机制可以保护未初始化的变量,您需要为所有变量添加前缀以在模拟模块中使用。 -
显示代码,创建一个最小的、可重现的示例
-
@Sirode 我试过了,我得到了通常的“s3.putObject 不是函数”
-
@slideshowp2 我刚刚添加了示例,抱歉耽搁了
-
在模拟模块之前需要添加
import AWS from 'aws-sdk';。
标签: node.js typescript unit-testing jestjs aws-sdk