You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:20:57