Typescript Jest 说我想模拟的类型上不存在模拟或模拟返回值

Posted

技术标签:

【中文标题】Typescript Jest 说我想模拟的类型上不存在模拟或模拟返回值【英文标题】:Typescript Jest says mock or mockReturnedValue do not exist on types I wish to mock 【发布时间】:2019-04-12 23:51:51 【问题描述】:

这是我想测试的一个类:

//Request.js
import axios, AxiosInstance from 'axios';
import config from './config';

const axiosSingleton: AxiosInstance = axios.create(
  baseURL: 'http://localhost:8080',
);

export default class Request 
  public async get<$ResponseType = any>(url: string): Promise<void> 
    const response = await axiosSingleton.get(url);
    return response.data;
  

当我尝试通过创建测试文件进行测试时,我不确定如何模拟 axios。我尝试了很多方法,包括 - spyOn 和自动模拟。但它们似乎不起作用。这是测试文件的一个版本,我不明白为什么它不起作用

// Request.test.js
import axios from 'axios';
import Request from './Request';

interface ITestResponseDataType 
  value: string


jest.mock('axios');

describe('Request Tests', () => 
  it('should call axios get with the right relativeUrl', async () => 
    const getMock = jest.fn();

    axios.create.mockReturnValue(
      get: getMock
    );

    getMock.mockResolvedValue(
      value: 'value'
    );

    const data = await new Request().get<ITestResponseDataType>('/testUrl');
    expect(getMock.mock.calls.length).toEqual(1);
    expect(data).toEqual(
      value: 'value'
    );
  );
);

我尝试运行测试时遇到的错误是 -

 TypeScript diagnostics (customize using `[jest-config].globals.ts-jest.diagnostics` option):
    src/common/api/Request.test.ts:15:18 - error TS2339: Property 'mockReturnValue' does not exist on type '(config?: AxiosRequestConfig | undefined) => AxiosInstance'.

    15     axios.create.mockReturnValue(

这个错误是有道理的,因为在 axios 中为 axios.create 定义的类型不应该允许在 .create 上调用 .mockReturnValue。那我怎么告诉 typescript jest 已经进去修改了呢?

【问题讨论】:

我遇到了同样的错误并在这里偶然发现......结果是我的模拟函数我实际上并没有调用 jest.fn() 【参考方案1】:

将模拟方法转换为jest.Mock,即

import axios from "axios"
import Request from "./Request";

// Create an Axios mock
// Don't worry about the order, Jest will hoist this above the imports
// See https://jestjs.io/docs/manual-mocks#using-with-es-module-imports
jest.mock("axios", () => (
  create: jest.fn()
))

// Customise the `create` mock method
(axios.create as jest.Mock).mockReturnValue(
  get: getMock
)

【讨论】:

这在被测试的模块/文件全局调用“Mocked”函数时不起作用,例如@ashwini 的情况const axiosSingleton: AxiosInstance = axios.create(...)。将 AxiosInstance 移动到函数中的局部变量是可行的,但现在您没有使用单例。还有其他想法吗? @DanB 当您使用jest.mock 时,它会将模拟实例提升到任何导入之上,因此它也将在测试期间用于生产文件中【参考方案2】:

只是对评分最高的答案的补充。我更喜欢在类型转换时维护类型定义。可以改写为

(axios as jest.Mocked<typeof axios>).create.mockReturnValue(
  get: getMock
);

【讨论】:

对我不起作用:``` 类型参数 ' get: jest.Mock; ' 不可分配给“AxiosInstance”类型的参数。输入 ' get: Mock; ' 缺少“AxiosInstance”类型的以下属性:默认值、拦截器、getUri、请求和 6 个更多。ts(2345) ```【参考方案3】:

您需要将 axios.create 方法替换为 Jest 模拟函数:

axios.create = jest.fn();

这应该允许你设置它的返回值。

【讨论】:

【参考方案4】:

我用 axios-mock-adapter 解决了这个问题,对我来说没有任何问题,并且还有助于嵌套调用。

    // src/request.ts
    import axios from "axios";
    export const axiosCreate = axios.create();
    export async function someRequest()
      axiosCreate.get("http://localhost/users");
    

    // src/__test__/request.test.ts
    import * as request from ".../request";
    import MockAdapter from "axios-mock-adapter";
    const mock = new MockAdapter(request.axiosCreate);
    it("Testing mock", async () => 
      mock.onGet("http://locahost/users").reply(200, "ok");
      const resp = await request.someRequest();
      expect(resp).toEqual("ok");
    );

希望能对某人有所帮助。

【讨论】:

以上是关于Typescript Jest 说我想模拟的类型上不存在模拟或模拟返回值的主要内容,如果未能解决你的问题,请参考以下文章

使用正确类型使用 Jest 和 Typescript 模拟 Express 请求

使用 jest typescript 模拟 Axios 的类型

用 Jest 和 Typescript 模拟一个全局对象

在 Typescript 中使用 Jest + Supertest 进行模拟

使用 typescript 模拟 forwardRef 组件 jest mockImplementation

如何使用 jest.fn() 在 jest 中使用 typescript 模拟函数