我正在测试一个相当简单的节点 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
时,我看到初始模拟被调用了两次。
我还尝试了以下方法:
beforeEach
:`(passport.authenticate as jest.Mock).resetMock正如我所见,问题的出现是因为你试图模拟的函数,
() => (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();
});