使用Jest在TypeScript中Mock类:测试依赖Summary类的Handler模块
嘿,我来帮你搞定这个Jest单元测试的问题!你提到要测试依赖Summary类的handler模块,先把你给出的Summary类代码片段整理好(看起来没写完,但核心结构已经清晰):
import DynamoDBClient from './ddbClient/DynamoDBClient' import { DynamoDB } from 'aws-sdk' import { iSummaryReader, iObsSummariesAttributes } from './Summary.d' import { JSONAPIResource } from '../JSONAPIResponse' export default class Summary { reader: iSummaryReader constructor(reader: iSummaryReader) { this.reader = reader } getSummary = async (keyName: string, keyVal: /* 你未写完的参数类型 */) => { // 这里是getSummary的实现逻辑 } }
下面是针对依赖这个Summary类的handler模块的单元测试方案,全程用Jest实现:
核心思路:Mock Summary类的依赖与行为
因为我们要测试的是handler模块,而非Summary类本身,所以需要把Summary类(以及它的依赖)mock掉,只关注handler和Summary之间的交互是否符合预期。
步骤1:先假设你的handler模块结构(可根据实际情况调整)
比如你的handler大概是这样的:
// handler.js import Summary from './Summary'; // 假设这是你要测试的handler函数 export const fetchSummaryHandler = async (event) => { // 这里可能有初始化reader的逻辑,比如从依赖容器获取或直接实例化 const reader = /* 你的reader实例化逻辑 */; const summaryService = new Summary(reader); try { const summaryData = await summaryService.getSummary(event.pathParameters.keyName, event.pathParameters.keyVal); return { statusCode: 200, body: JSON.stringify(summaryData) }; } catch (error) { return { statusCode: 500, body: JSON.stringify({ error: error.message }) }; } };
步骤2:编写Jest测试用例
// handler.test.js import { fetchSummaryHandler } from './handler'; import Summary from './Summary'; // 用Jest mock整个Summary类 jest.mock('./Summary'); describe('fetchSummaryHandler', () => { // 每个测试前清除mock的调用记录,避免测试间污染 beforeEach(() => { Summary.mockClear(); }); test('should call Summary.getSummary with correct params and return 200 response', async () => { // 1. 预设mock的getSummary方法返回值 const mockSummaryData = { id: 'summary-123', attributes: { temperature: 25, humidity: 60 } }; const mockGetSummary = jest.fn().mockResolvedValue(mockSummaryData); // 2. 让Summary类实例化后返回带有mock方法的对象 Summary.mockImplementation(() => ({ getSummary: mockGetSummary })); // 3. 构造测试用的event对象 const mockEvent = { pathParameters: { keyName: 'deviceId', keyVal: 'dev-001' } }; // 4. 调用handler const response = await fetchSummaryHandler(mockEvent); // 5. 验证交互是否正确 // 验证Summary是否被实例化了一次 expect(Summary).toHaveBeenCalledTimes(1); // 验证getSummary是否用正确的参数调用 expect(mockGetSummary).toHaveBeenCalledWith('deviceId', 'dev-001'); // 验证返回的响应是否符合预期 expect(response.statusCode).toBe(200); expect(JSON.parse(response.body)).toEqual(mockSummaryData); }); test('should return 500 response when Summary.getSummary throws error', async () => { // 1. 预设mock的getSummary抛出错误 const mockError = new Error('Failed to read summary from database'); const mockGetSummary = jest.fn().mockRejectedValue(mockError); Summary.mockImplementation(() => ({ getSummary: mockGetSummary })); // 2. 构造测试event const mockEvent = { pathParameters: { keyName: 'deviceId', keyVal: 'dev-001' } }; // 3. 调用handler并验证响应 const response = await fetchSummaryHandler(mockEvent); expect(response.statusCode).toBe(500); expect(JSON.parse(response.body)).toEqual({ error: 'Failed to read summary from database' }); // 验证错误确实被触发了 expect(mockGetSummary).toHaveBeenCalledWith('deviceId', 'dev-001'); }); });
额外注意事项
- 如果你的handler是通过依赖注入的方式传入Summary实例(而非在handler内部new),测试会更简单:直接在测试里传入一个mock的Summary实例即可,不需要用
jest.mock整个类。 - 若需要测试Summary类本身的逻辑,才需要mock它的依赖
iSummaryReader(比如mock DynamoDBClient的行为),但当前场景是测试handler,重点在隔离Summary。 - 可以用
jest.spyOn来mock单个方法,而非整个类,比如如果Summary有多个方法,只mockgetSummary的话,用jest.spyOn(Summary.prototype, 'getSummary').mockResolvedValue(...)会更灵活。
内容的提问来源于stack exchange,提问作者user3559247
相关产品推荐
相关产品推荐

