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

如何为下述控制器创建测试?是否需要为该接口代码编写测试用例

是否需要为该接口编写测试?

必须写。这个接口是用户信息更新的核心入口,直接关联三个高风险出问题的环节:

  • 代码硬编码从req.user.user路径提取当前登录用户信息,一旦鉴权中间件返回的用户字段结构调整,接口会直接抛出500错误
  • 接口涉及用户身份权限逻辑,必须保证不会被恶意构造请求绕过,出现越权修改他人信息的问题
  • 控制器作为请求入口,要保证请求体参数、上下文用户信息正确透传给服务层,同时把服务层返回结果正确返回给调用方,不能出现参数错传、返回值篡改的问题
如何为该控制器创建测试用例

这是典型的NestJS框架控制器代码,推荐用Jest做单元测试,通过mock隔离依赖的UserService层,只校验控制器本身的逻辑,不需要连接数据库、启动完整服务,服务层的业务逻辑单独在UserService的测试里覆盖即可。

必覆盖测试场景

  • 正常流程场景:构造合法的UpdateUserDto参数、携带正确登录用户信息的请求对象,调用控制器方法,校验两点:一是userService.update被调用时的入参完全正确,第一个参数是req.user.user对应的登录用户信息,第二个参数是传入的DTO对象;二是控制器返回值和Service层返回的结果完全一致
  • 鉴权异常场景:构造缺少req.user.user字段的请求对象(对应鉴权失效、登录态过期的情况),校验控制器会抛出预期错误
  • 参数校验场景:构造不符合UpdateUserDto校验规则的请求体(比如字段类型错误、必填字段缺失、字段长度超出限制),校验请求会被参数校验层拦截返回对应错误(这个场景如果全局校验管道是统一配置的,也可以放到e2e测试里覆盖)
  • 越权风险校验:确认控制器逻辑没有从请求体中读取用户ID/用户标识覆盖req.user.user的取值,从入口层堵死越权修改的可能

测试代码参考

import { Test, TestingModule } from '@nestjs/testing';
import { UserController } from './user.controller';
import { UserService } from './user.service';
import { UpdateUserDto } from './dto/update-user.dto';

describe('UserController', () => {
  let controller: UserController;
  let mockUserService: { update: jest.Mock };

  beforeEach(async () => {
    // 模拟依赖的UserService,隔离真实业务逻辑
    mockUserService = {
      update: jest.fn()
    };
    const moduleRef: TestingModule = await Test.createTestingModule({
      controllers: [UserController],
      providers: [
        {
          provide: UserService,
          useValue: mockUserService
        }
      ]
    }).compile();

    controller = moduleRef.get<UserController>(UserController);
  });

  test('正常请求时应正确透传参数并返回Service层结果', async () => {
    const testUpdateDto: UpdateUserDto = {
      nickname: '测试昵称',
      avatar: 'test-avatar-path'
    };
    const testReq = {
      user: {
        user: { id: 1001, username: 'test_account' }
      }
    };
    const mockServiceReturn = {
      id: 1001,
      username: 'test_account',
      nickname: '测试昵称',
      avatar: 'test-avatar-path'
    };
    mockUserService.update.mockResolvedValue(mockServiceReturn);

    const result = await controller.update(testUpdateDto, testReq);

    // 校验Service调用参数正确
    expect(mockUserService.update).toHaveBeenCalledTimes(1);
    expect(mockUserService.update).toHaveBeenCalledWith(testReq.user.user, testUpdateDto);
    // 校验返回值正确
    expect(result).toEqual(mockServiceReturn);
  });

  test('请求上下文缺少登录用户信息时应抛出错误', async () => {
    const testUpdateDto: UpdateUserDto = { nickname: '测试昵称' };
    const invalidReq = { user: {} }; // 模拟鉴权中间件未正确注入用户信息的情况

    await expect(controller.update(testUpdateDto, invalidReq)).rejects.toThrow();
  });
});

如果需要做接口级别的端到端测试,可以搭配supertest发送真实HTTP请求,携带合法/非法的鉴权令牌、构造不同的请求体,校验接口的HTTP状态码、返回结构是否符合预期,这类测试不需要关心控制器和服务的内部调用逻辑,只校验接口对外的表现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 01:48:15