如何使用TypeScript模拟Express的Request、Response和NextFunction对象?

22

这是我的中间件:

export const isLogged = () => (req: Request, res: Response, next: NextFunction) => next();

我正在尝试创建一个单元测试,但是我无法使用正确的类型进行mock:

const middleware = middlewares.isLogged()

middleware(
  jest.fn<Request>(), // Expected 0-2 type argument but got 1
  jest.fn<Response>(),
  jest.fn<NextFunction>(),
);

这不起作用,我尝试过模拟express模块,但还没有让它工作。 我该如何模拟它们?

2个回答

32

前两个参数分别是Request对象和Response对象。

如果您的代码不使用reqres,您可以使用空对象作为模拟,并告诉TypeScript将这些模拟视为预期类型,如下所示:

it('should call next', () => {
  const next = jest.fn();
  middleware(
    {} as Request,
    {} as Response,
    next,
  );
  expect(next).toHaveBeenCalled();  // SUCCESS
});

更新

如果您想在RequestResponse上模拟其他属性,则可以将它们添加到您的模拟对象中。

您的模拟对象可能不会实现完整的RequestResponse接口,因此您可以使用类似于Partial<Request>Partial<Response>的东西,或者仅告诉TypeScript您要使用类型any来为模拟对象“退出类型检查并让值通过编译时检查”:

it('should call next', () => {
  const req: any = {
    get: jest.fn((name) => {
      if (name === 'content-type') return 'text/plain';
    })
  };
  const res: any = {
    send: jest.fn()
  }
  const next = jest.fn();
  middleware(
    req,
    res,
    next,
  );
  expect(next).toHaveBeenCalled();  // SUCCESS
});

我该如何模拟 req.get() 函数? - Christopher Francisco
@ChristopherFrancisco 我更新了我的回答,包括在 reqres 上模拟属性。 - Brian Adams
将模拟对象声明为 req: any 就解决了问题。我之前没有尝试过这种方法,因为我的中间件本地参数已经被定义为 req: Request 类型,但看起来它仍然可以正常工作。谢谢! - Christopher Francisco
谢谢您。您能否提供一个完整的例子?例如,我不确定中间件是从哪里来的。 - Petrus Theron

1
您可以使用 Typescript 中的 工具类型。例如:
const middleware = middlewares.isLogged()

const req: Partial<Request> = {};
const res: Partial<Response> = {};
const next: NextFunction = jest.fn();

middleware(req, res, next);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接