Jest.spyOn测试express-validator报"Cannot use spyOn..."错误的解决方法
Express-validator validationResult Jest Mock 报错修复
错误含义
“Cannot use spyOn on a primitive value; undefined given” 表示调用jest.spyOn时,第二个参数指定的属性在第一个参数对象中不存在(值为undefined),且spyOn仅能用于监听对象的方法,无法作用于原始值。
问题根源
控制器中通过命名导入引入validationResult:
import { validationResult } from "express-validator";
但测试代码里导入了express-validator的默认导出对象validator,并试图监听它的validationResult属性——而express-validator的默认导出对象并不包含该属性,导致spyOn获取到的目标属性为undefined,触发报错。
修复方案
以下两种方式均可解决问题:
方式1:导入所有导出内容,正确监听命名导出的函数
修改测试代码的导入逻辑,用import * as validator from "express-validator"将所有导出内容加载到validator对象上,确保validator.validationResult存在:
import RegistrationController from "./registration.controller"; // 修改导入方式:将所有导出内容导入到validator对象 import * as validator from "express-validator"; describe("registration", () => { const { registration } = RegistrationController; let req = {}, res = { status: jest.fn().mockReturnThis(), json: jest.fn() }, next = jest.fn(); it('验证失败时应调用next("Houston, we have a problem")', async () => { const validationResultMock = { isEmpty: () => false, }; jest .spyOn(validator, "validationResult") .mockImplementation(() => validationResultMock); await registration(req, res, next); expect(next).toBeCalledWith("Houston, we have a problem"); }); });
方式2:直接mock整个express-validator模块
通过jest.mock直接模拟模块导出,逻辑更简洁:
import RegistrationController from "./registration.controller"; import { validationResult } from "express-validator"; // mock整个express-validator模块,保留其他导出的真实实现 jest.mock("express-validator", () => ({ ...jest.requireActual("express-validator"), validationResult: jest.fn(), })); describe("registration", () => { const { registration } = RegistrationController; let req = {}, res = { status: jest.fn().mockReturnThis(), json: jest.fn() }, next = jest.fn(); it('验证失败时应调用next("Houston, we have a problem")', async () => { // 指定validationResult的返回值 (validationResult as jest.Mock).mockReturnValue({ isEmpty: () => false, }); await registration(req, res, next); expect(next).toBeCalledWith("Houston, we have a problem"); }); });
注:上述代码中给res对象mock了status和json方法,可避免测试过程中出现“res.status is not a function”的控制台警告。
内容的提问来源于stack exchange,提问作者BuGaGa
相关产品推荐
相关产品推荐

