【问题标题】:Test NestJs API controller with Jest用 Jest 测试 NestJs API 控制器
【发布时间】:2021-02-03 03:05:40
【问题描述】:

我正在使用 NestJs 和 mysql 创建一个 API。 我用于创建新实体的控制器功能运行良好,但是,我无法测试响应为 400 错误的用例。

这是控制器功能:

@Controller('pubs')
export class PubsController {
   constructor(private readonly pubsService: PubsService) {}
   @Post()
   async create(@Body() createPubDto: CreatePubDto, @Res() res: Response): Promise<void> {
     this.pubsService.create(createPubDto)
       .then(() => res.status(201).json())
       .catch(err => res.status(401).json({ err }));
   }
}

这是测试文件:

describe('PubsController', () => {
  let controller: PubsController;
  let service: PubsService;
  const mockResponse = () => {
    const res: any = {};
    res.status = jest.fn().mockReturnValue(res);
    res.json = jest.fn().mockReturnValue(res);
    return res;
  };

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      controllers: [PubsController],
      providers: [PubsService, {
        provide: getRepositoryToken(Pub),
        useValue: {},
      }],
    }).compile();

    controller = module.get<PubsController>(PubsController);
    service = module.get<PubsService>(PubsService);
  });

  afterEach(() => {
    jest.resetAllMocks();
    jest.clearAllMocks();
  });

  describe('create success', () => {
    const res = mockResponse();
    it('Should create a pub', async () => {
      const req = mockedPub;
      jest.spyOn(service, 'create').mockResolvedValue(mockedPub);
      await controller.create(req, res);
      expect(res.status).toHaveBeenCalledWith(201);
    });
    it('Should return 400 if the body is not correct', async () => {
      const req: any = {};
      jest.spyOn(service, 'create').mockResolvedValue(req);
      await controller.create(req, res);
      expect(res.status).toHaveBeenCalledWith(400);
    });
  }) 
});

“应该创建一个酒吧”运行良好,但是当我给创建函数一个空对象时,测试给我一个 201 res.status。

    expect(jest.fn()).toHaveBeenCalledWith(...expected)

    Expected: 400
    Received: 201

有人知道为什么吗?

【问题讨论】:

    标签: api jestjs nestjs


    【解决方案1】:

    首先,您是否在代码中的任何位置使用任何验证管道来验证传入的CreatePubDto,例如在您的main.ts 文件或pubService 中?

    其次,在你应该失败的测试中,你写了jest.spyOn(service, 'create').mockResolvedValue(req);,它解决了,因此你不会在控制器级别捕获任何错误,这意味着你进入控制器逻辑的.then(() =&gt; res.status(201).json())

    您应该将测试重构为:

    it('Should return 400 if the body is not correct', async () => {
        const error: any = { message: 'bad DTO provided', code: 400 }; // <== this is where you mock the logic of your service to throw an error
        jest.spyOn(service, 'create').mockRejectedValue(error);
        await controller.create(req, res);
        expect(res.status).toHaveBeenCalledWith(400);
    });
    

    这样你告诉 Jest 在调用 create 方法时抛出一个错误。我放置了可能抛出的示例错误,但您可以随意使用您自己的错误格式来抛出。

    另外,不要忘记将控制器中返回的错误代码与测试中预期的代码对齐。我猜400 在这个用例中更合适。

    【讨论】:

    • 感谢您的回复(和欢迎 :))。我不为 createPubDto 使用任何验证管道。如果 Pub 发送不是一个好的,它是控制器功能。这里是服务的创建函数:create(pub: Pub): Promise&lt;Pub&gt; { return this.PubsRepository.save(pub); } 有了你预先确定的更改,我有以下错误:expect(jest.fn()).toHaveBeenCalledWith(...expected) Expected: 400 Number of calls: 0 这是否意味着我必须在服务函数中移动'then - catch'?
    猜你喜欢
    • 2022-01-06
    • 1970-01-01
    • 2019-08-29
    • 2020-11-16
    • 2019-08-23
    • 1970-01-01
    • 2019-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多