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

如何用Jest测试含RxJS .pipe的代码?遇pipe未定义错误

问题:Jest测试RxJS pipe时出现"Cannot read properties of undefined (reading 'pipe')"错误

我有一段服务代码,通过this.httpService.post发起请求,并用RxJS的.pipe结合catchError处理错误。编写Jest测试时,我mock了httpService.post让它返回Observable对象,但测试执行到.pipe时抛出错误:TypeError: Cannot read properties of undefined (reading 'pipe')。

待测试代码

const { data: plan } = await firstValueFrom(
  this.httpService
    .post<CreatePlanPagarmeInterface>(
      `${PagarmeConfig.baseUrl}/plans`,
      pagarmeBody,
      PagarmeConfig.auth,
    )
    .pipe(
      catchError(() => {
        throw new BadRequestException(
          'Error to create plan.',
        );
      }),
    ),
);

测试代码

describe('createPlanMonth', () => {
  it('shoud be able to create a new plan month', async () => {
    jest.spyOn(httpService, 'post').mockReturnValueOnce(
      of({
        status: 200,
        statusText: 'OK',
        config: {},
        headers: {},
        data: resultPagarmeMock,
      }),
    );

    const result = await planService.createPlanMonth(mockPlan);

    expect(result).toEqual(resultMockPlan);
  });
});

解决方案

原因

错误核心是this.httpService.post()调用后返回了undefined,而非预期的Observable,导致后续.pipe调用失败。通常是因为mock的httpService.post没有绑定到服务实际使用的实例上。

修复步骤

  1. 注入正确的mock实例:如果是NestJS这类依赖注入框架,需在测试模块中显式提供mock的HttpService,确保服务使用的是该mock对象而非真实实例。
  2. 正确获取mock实例并spy:通过测试模块拿到httpService的mock实例后,再对其post方法进行spy,保证mock真正生效。
  3. 验证Observable返回值:确保测试代码正确导入RxJS的of操作符,返回合法的Observable对象。

修正后的测试代码示例

import { of } from 'rxjs';
import { Test, TestingModule } from '@nestjs/testing';
import { PlanService } from './plan.service';
import { HttpService } from '@nestjs/axios';
import { PagarmeConfig } from './config/pagarme.config';

// 定义你的mock数据
const resultPagarmeMock = { /* 模拟的Pagarme返回数据 */ };
const mockPlan = { /* 模拟的入参数据 */ };
const resultMockPlan = { /* 预期的返回结果 */ };

describe('PlanService', () => {
  let planService: PlanService;
  let httpService: HttpService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        PlanService,
        {
          provide: HttpService,
          useValue: { post: jest.fn() }, // 初始化mock的post方法
        },
      ],
    }).compile();

    planService = module.get<PlanService>(PlanService);
    httpService = module.get<HttpService>(HttpService);
  });

  describe('createPlanMonth', () => {
    it('should be able to create a new plan month', async () => {
      jest.spyOn(httpService, 'post').mockReturnValueOnce(
        of({
          status: 200,
          statusText: 'OK',
          config: {},
          headers: {},
          data: resultPagarmeMock,
        }),
      );

      const result = await planService.createPlanMonth(mockPlan);

      expect(result).toEqual(resultMockPlan);
      // 验证post方法的调用参数是否符合预期
      expect(httpService.post).toHaveBeenCalledWith(
        `${PagarmeConfig.baseUrl}/plans`,
        expect.any(Object), // 替换为实际的pagarmeBody参数
        PagarmeConfig.auth,
      );
    });
  });
});

关键修复点

  • 在测试模块的providers中提前配置mock的HttpService,确保服务依赖的是该mock实例
  • 通过module.get获取mock实例后再执行spy,避免spy对象与服务实际使用对象不匹配
  • 增加对post方法调用参数的断言,验证请求逻辑的正确性

内容的提问来源于stack exchange,提问作者wiliamvj

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 17:31:00