Vitest测试:验证signup函数是否调用Mongoose的User.create方法
问题排查与解决
核心问题分析
测试失败主要源于三个常见误区:
signup是异步函数,测试未等待其执行完成就触发断言- 请求对象结构不符合Express规范(参数未放在
req.body层级) - Mock的
User.create未返回Promise,和Mongoose原方法的异步行为不匹配
具体修复步骤
1. 修正请求对象结构
Express中前端传递的参数默认存放在req.body中,你的signup函数必然是读取该字段下的内容,所以要调整请求对象的嵌套结构:
const request = { body: { "firstName": 'first', "lastName": 'last', "email": 'test@gmail.com', "password": 'test-password', "passwordConfirm": 'test-password', "city": 'test-city', "phoneNumber": +251946612595, } };
2. 处理异步函数的测试逻辑
由于signup内部调用了异步的User.create,它本身是异步函数,测试时必须等待其执行完成,否则断言会在User.create调用前触发:
将测试函数改为async,并用await调用signup:
it('should call the create method from Mongoose', async () => { // ... 其他代码 await signup(request, response, mockNext); // ... 断言逻辑 });
3. 修正User.create的Mock实现
Mongoose的create方法返回Promise,你的Mock需要对齐这个异步行为,否则会导致函数内部流程异常:
User.create.mockImplementationOnce(() => Promise.resolve(request.body));
完整修复后的测试代码
import { describe, it, expect, vi } from 'vitest'; import { signup } from '../controllers/authController'; import User from '../models/userModel'; vi.mock('../models/userModel'); describe('signup()', () => { const request = { body: { "firstName": 'first', "lastName": 'last', "email": 'test@gmail.com', "password": 'test-password', "passwordConfirm": 'test-password', "city": 'test-city', "phoneNumber": +251946612595, } }; const response = { "status": vi.fn().mockReturnThis(), "json": vi.fn().mockReturnThis(), "cookie": vi.fn(), }; const mockNext = vi.fn(); it('should call the create method from Mongoose', async () => { User.create.mockImplementationOnce(() => Promise.resolve(request.body)); await signup(request, response, mockNext); expect(User.create).toHaveBeenCalled(); // 可选:进一步校验调用参数是否正确 expect(User.create).toHaveBeenCalledWith(request.body); }); });
额外验证点
如果测试仍失败,可以检查:
signup函数是否有参数校验逻辑(如密码长度、邮箱格式),若测试参数不符合规则,函数会提前返回,不会执行User.create- 确认
vi.mock('../models/userModel')的路径正确,是否成功Mock了User模型
内容的提问来源于stack exchange,提问作者Naod Ararsa
相关产品推荐
相关产品推荐

