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

NestJS单元测试遇Jest匹配器错误:received value must be a promise

解决NestJS单元测试中的Matcher error: received value must be a promise错误

我在给NestJS应用编写单元测试时,碰到了一个无法解决的错误:Matcher error: received value must be a promise,但明明已经对Promise做了处理。

相关代码

Service层的update方法

async update(uname: string, updateUserDto: UpdateUserDTO): Promise<Users> {
  const updateUser = await prisma.users.findUnique({
    where: {
      username: uname,
    },
  });

  if (!updateUser || updateUser.username !== uname) {
    throw new NotFoundException('User not found');
  }

  await prisma.tasks.updateMany({
    where: {
      userId: uname,
    },
    data: {
      userId: uname,
    },
  });
  return prisma.users.update({
    where: {
      username: uname,
    },
    data: {
      ...updateUserDto,
    },
  });
}

Controller层的update方法

@Patch(':uname')
update(@Param('uname') uname: string, @Body() updateUserDto: UpdateUserDTO) {
  return this.usersService.update(uname, updateUserDto);
}

测试代码及Mock配置

测试用例

describe('Update a user', () => {
  it('should update the username of a user', async () => {
    const updatedUser: UpdateUserDTO = {
      name: 'Hulk',
    };
    await expect(
      controller.update('wolverine', updatedUser)
    ).resolves.toEqual({
      username: 'wolverine',
      ...updatedUser,
    });
  });
});

Service的Mock实现

update: jest
  .fn()
  .mockImplementation((username: string, user: UpdateUserDTO) =>
    Promise.resolve({ username, ...user })
  ),

问题原因及解决办法

这个错误本质是传给expect()的值并非Promise,即便看起来controller的update方法返回了Service层的Promise,也可能因为写法或配置问题导致识别异常。以下是可行的解决步骤:

1. 替换断言写法

放弃.resolves匹配器,直接await方法结果后再断言,这种写法更稳妥,也能避免jest匹配器的潜在问题:

it('should update the username of a user', async () => {
  const updatedUser: UpdateUserDTO = {
    name: 'Hulk',
  };
  // 先await获取结果
  const response = await controller.update('wolverine', updatedUser);
  // 直接断言结果
  expect(response).toEqual({
    username: 'wolverine',
    ...updatedUser,
  });
  // 额外断言Service方法是否被正确调用
  expect(service.update).toHaveBeenCalledWith('wolverine', updatedUser);
});

2. 验证Mock的Service注入正确性

确保测试模块中,controller依赖的是你Mock的UsersService实例,而非真实Service:

let controller: UsersController;
let service: UsersService;

beforeEach(async () => {
  const module: TestingModule = await Test.createTestingModule({
    controllers: [UsersController],
    providers: [
      {
        provide: UsersService,
        useValue: {
          update: jest.fn().mockImplementation((username, user) => 
            Promise.resolve({ username, ...user })
          ),
          // 其他需要Mock的Service方法
        },
      },
    ],
  }).compile();

  controller = module.get<UsersController>(UsersController);
  service = module.get<UsersService>(UsersService);
});

如果使用真实Service,测试环境中未配置的Prisma会导致数据库连接异常,虽然也会触发Promise reject,但错误提示不会是"received value must be a promise"。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 17:45:40