Jest mockImplementation 似乎没有覆盖初始模拟模块的函数

问题描述 投票:0回答:1

我正在测试一个相当简单的节点 API 端点:

import { getRaces } from '@/services/races';
import { Request, Response, Router } from 'express';
import passport from 'passport';

export default (app: Router) => {
  app.get('/races', passport.authenticate('jwt', { session: false }), async (req: Request, res: Response) => {
    console.log(req);
    if (req.user) {
      res.status(200).json({ races: await getRaces() });
    } else {
      res.status(401).json({ error: 'Unauthorized' });
    }
  });
};

我的初始模拟似乎按我的预期工作,在第一个测试中,测试用户被成功模拟,测试收到 200 状态,并且还能够确认模拟数据已正确返回。

import express from 'express';
import passport from 'passport';
import request from 'supertest';

import { getRaces } from '@/services/races';

import charactersRoute from './races';

jest.mock('@/services/races');
jest.mock('passport', () => ({
  authenticate: jest.fn(() => (req, _res, next) => {
    req.user = { id: 'test-user' }; // Mock authenticated user
    next();
  }),
}));

const app = express();
app.use(express.json());
const router = express.Router();
charactersRoute(router);
app.use(router);

describe('GET /races', () => {
  it('should return 200 and a list of races when authenticated', async () => {
    const mockRaces = [
      { id: 1, name: 'Elf' },
      { id: 2, name: 'Dwarf' },
    ];
    (getRaces as jest.Mock).mockResolvedValue(mockRaces);

    const response = await request(app).get('/races');

    expect(response.status).toBe(200);
    expect(response.body).toEqual({ races: mockRaces });
  });

  it('should return 401 when not authenticated', async () => {
    (passport.authenticate as jest.Mock).mockImplementation(() => (_req, _res, next) => {
      next();
    });

    const response = await request(app).get('/races');

    expect(response.status).toBe(401);
    expect(response.body).toEqual({ error: 'Unauthorized' });
  });
});


但是,似乎我在尝试测试未经身份验证的用户时设置的

mockImplementation
功能在测试运行时并未受到打击,而是初始护照模拟受到打击。当我控制台记录初始模拟函数以及
mockImplementation
passport.authenticate
时,我看到初始模拟被调用了两次。

我还尝试了以下方法:

  • 模拟护照后导入护照,以防范围出现问题。尽管我的 prettier 和 eslint 插件将导入重新排序到文件顶部。
  • 在我尝试重置模拟的位置添加
    beforeEach
    :`(passport.authenticate as jest.Mock).resetMock
javascript typescript express jestjs passport.js
1个回答
0
投票

正如我所见,问题的出现是因为你试图模拟的函数,

() => (req, _res, next) => {};

实际上是一个柯里化函数。外部函数在

mockImplementation
调用之前调用,在应用程序初始化时,在此代码块中的某处

const app = express();
app.use(express.json());
const router = express.Router();
charactersRoute(router);
app.use(router);

此后,仅调用内部记忆函数。

为了达到预期的结果,您应该模拟内部函数。然后你也应该为内部函数调用

mockImplementation

const authHandler = jest.fn((req, _res, next) => {
  req.user = { id: 'test-user' }; // Mock authenticated user
    next();
});

jest.mock('passport', () => ({
  authenticate: jest.fn(() => authHandler),
}));

...

authHandler.mockImplementation((_req, _res, next) => {
  next();
});

© www.soinside.com 2019 - 2024. All rights reserved.