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

如何在@fluffy-spoon/substitute中为不同测试用例设置不同返回值

问题解决:在NestJS Jest测试中为@fluffy-spoon/substitute Mock设置不同返回值

问题根源

你当前的contractDocumentService Mock实例是在describe作用域下创建的,所有测试用例会共享这个实例。第一个测试用例设置的返回值会被保留,后续测试用例的新设置无法覆盖原有匹配规则,导致所有测试都返回第一个值。

解决方案

方案1:每个测试用例创建全新Mock实例

将Mock实例的创建移到beforeEach钩子中,确保每个测试用例都使用独立的Mock对象,避免状态污染:

import Substitute, { Arg, SubstituteOf } from '@fluffy-spoon/substitute';
// ...其他导入

describe('Test CollaboratorService', () => {
  let contractDocumentService: SubstituteOf<ContractDocumentService>;
  let collaboratorService: CollaboratorService;

  beforeEach(async () => {
    // 每个测试前重新创建Mock实例
    contractDocumentService = Substitute.for<ContractDocumentService>();
    
    const moduleRef = await Test.createTestingModule({
      imports: [],
      controllers: [],
      providers: [
        CollaboratorService,
        {
          provide: 'ContractDocumentService',
          useValue: contractDocumentService,
        },
      ],
    }).compile();

    collaboratorService = moduleRef.get(CollaboratorService);
  });

  it('should return collaborators with first contract document', async () => {
    // 设置当前测试的Mock返回值
    contractDocumentService
      .findOneOrFail(Arg.any())
      .returns(Promise.resolve(firstContractDocument));

    // 执行测试逻辑并断言
    const result = await collaboratorService.yourMethod('some-id');
    expect(result).toEqual(/* 预期结果 */);
  });

  it('should return collaborators with second contract document', async () => {
    // 设置当前测试的Mock返回值
    contractDocumentService
      .findOneOrFail(Arg.any())
      .returns(Promise.resolve(secondContractDocument));

    // 执行测试逻辑并断言
    const result = await collaboratorService.yourMethod('another-id');
    expect(result).toEqual(/* 预期结果 */);
  });
});

方案2:重置Mock状态(复用实例)

如果不想每次创建新实例,可以在beforeEach中调用clearSubstitute()重置Mock的所有调用记录和返回值设置:

import Substitute, { Arg } from '@fluffy-spoon/substitute';
// ...其他导入

describe('Test CollaboratorService', () => {
  const contractDocumentService = Substitute.for<ContractDocumentService>();
  let collaboratorService: CollaboratorService;

  beforeEach(async () => {
    // 重置Mock状态
    contractDocumentService.clearSubstitute();
    
    const moduleRef = await Test.createTestingModule({
      // ...与之前相同的模块配置
    }).compile();

    collaboratorService = moduleRef.get(CollaboratorService);
  });

  // 测试用例写法与方案1一致
});

关于具体参数匹配返回Proxy的说明

当你尝试用具体参数替代Arg.any()时出现Proxy 'SubstituteJS'} jest,大概率是因为之前已存在Arg.any()的匹配规则。@fluffy-spoon/substitute会按设置顺序匹配规则,优先命中先设置的Arg.any(),导致后续的具体参数匹配从未触发。通过上述两种方案重置Mock状态后,再设置具体参数匹配就能正常生效。

内容的提问来源于stack exchange,提问作者Anto P V

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 18:15:42