使用spyOn mock返回Express Response的函数时出现类型不匹配报错
问题根因
- 这个TypeScript报错是两个问题叠加导致的:
- 你给
getTokenExample声明的返回类型是Express的Response对象,这个对象自带accepted、badRequest、clientError等20+个必填属性,而你传入resolveTo的mock值只有body一个字段,远达不到类型要求 - 你之前尝试对mock对象强制转成Response类型没生效,是因为TS的类型断言规则:如果源类型(仅含body属性的简陋对象)和目标类型(含20+必填属性的Express Response)没有足够的结构重叠,单层级的
as类型断言会被TS直接拦截,不会生效
- 你给
- 补充错位问题:原函数实际是调用superagent发请求,本来返回的是superagent自带的Response类型,和Express Response不是同一个类型,本身的类型声明就存在逻辑错位
解决方法
1. 用双层类型断言修正spy的mock值
先修复你原代码里缺闭合花括号的语法问题,用as unknown as的双层断言绕过TS对属性数量的校验,这也是测试场景下的通用写法,不需要硬凑齐Express Response的所有冗余属性:
spyOn(tokenExample, "getTokenExample").and.resolveTo({ body: { token: "mocked_token" } } as unknown as Express.Response);
原理:先把mock对象转成TS的顶级未知类型
unknown,再转成目标Express Response类型,TS就不会再校验两边的属性差异,也就不会抛出缺属性的类型错误。
2. 单测场景直接替换模块mock,跳过类型校验
如果是在单元测试环境,不需要严格匹配完整的Express Response类型,可以直接用jest.mock重写整个模块的返回值,写起来更灵活:
jest.mock("./tokenExample模块的路径", () => ({ getTokenExample: jest.fn().mockResolvedValue({ body: { token: "mocked_token" } }) }));
这种方式不会触发原函数类型定义的强制校验,适合不需要严格类型约束的测试场景。
3. 修正根源的类型声明错位
你当前的类型错位本质是错误标注了getTokenExample的返回值类型:
原函数是通过superagent发起请求,实际返回的是superagent的Response对象,和Express Response是完全不同的两个类型。如果硬给它标注成Express Response,哪怕mock能跑通,线上真实请求返回的对象也不匹配Express Response的结构,后续调用时一样会出问题,最好检查函数的返回值类型标注,改成和实际返回值匹配的superagent.Response类型,从根源上消除类型不匹配的问题。
内容的提问来源于stack exchange,提问作者Jorgio
相关产品推荐
相关产品推荐

