如何使用jest和supertest模拟express中间件类方法?

okxuctiv  于 12个月前  发布在  Jest
关注(0)|答案(1)|浏览(105)

我在使用jest和supertest模拟类中的方法时很难获得预期的结果,我想知道是否有人知道解决方案。
我试图用模拟版本绕过原始类中的verifyAuthenticated方法,因为它会调用外部服务。
这是一个简单的例子

import express, { Application, Request, Response } from "express";
import authMiddleware from "./AuthMiddleware";

const app: Application = express();

app.disable("x-powered-by");

const rootHandler = (request: Request, response: Response) => {
  response.json({ status: "online" });
};

app.get("/", [authMiddleware.verifyAuthenticated, rootHandler]);

export default app;
import { Request, Response, NextFunction } from "express";

class AuthMiddleware {
  constructor() {
    console.log("AuthMiddleware instance created");
  }

  verifyAuthenticated = (request: Request, response: Response, next: NextFunction) => {
    // In the real world this would call out to an external service and verify user credentials.
    console.log("This is the real deal");
    next();
  };
}

export default new AuthMiddleware();
import request from "supertest";
import app from "../src/app";
import authMiddleware from "../src/AuthMiddleware";
import { NextFunction, Request, Response } from "express";

describe("GET /", () => {
  test("Should return online.", async () => {
    jest
      .spyOn(authMiddleware, "verifyAuthenticated")
      .mockImplementation((req: Request, res: Response, next: NextFunction) => {
        console.log("This is the mock deal");
        next();
      });

    const agent = request(app);
    const response = await agent.get("/").send();

    expect(response.statusCode).toBe(200);
    expect(response.headers["content-type"]).toContain("application/json");
    expect(response.body.status).toBe("online");
  });
});

测试结果如下:

> [email protected] test
> jest

  console.log
    AuthMiddleware instance created

      at new AuthMiddleware (src/AuthMiddleware.ts:5:13)

  console.log
    This is the real deal

      at AuthMiddleware.verifyAuthenticated (src/AuthMiddleware.ts:9:13)

 PASS  tests/app.test.ts
  GET /
    ✓ Should return online. (39 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.316 s, estimated 3 s
Ran all test suites.

我期待着This is the mock deal。我已经尝试了多种不同的变种导入和重写类,但没有一个工作,他们都给出了相同的结果给予。

1yjd4xko

1yjd4xko1#

在导入app之前模拟authMiddleware.verifyAuthenticated()方法。我们可以使用动态import()方法导入app
app.test.ts

import request from 'supertest';
// import app from './app';
import authMiddleware from './AuthMiddleware';
import { NextFunction, Request, Response } from 'express';

describe('GET /', () => {
    test('Should return online.', async () => {
        jest
            .spyOn(authMiddleware, 'verifyAuthenticated')
            .mockImplementation((req: Request, res: Response, next: NextFunction) => {
                console.log('This is the mock deal');
                next();
            });

        const app = (await import('./app')).default;
        const agent = request(app);
        const response = await agent.get('/').send();

        expect(response.statusCode).toBe(200);
        expect(response.headers['content-type']).toContain('application/json');
        expect(response.body.status).toBe('online');
    });
});

试验结果:

console.log
    AuthMiddleware instance created

      at new AuthMiddleware (stackoverflow/77281063/AuthMiddleware.ts:5:11)

  console.log
    This is the mock deal

      at stackoverflow/77281063/app.test.ts:11:13

 PASS  stackoverflow/77281063/app.test.ts
  GET /
    ✓ Should return online. (91 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.747 s, estimated 7 s

相关问题