Jest mocking TypeScript class “No overload expects 1 type arguments”

为君一笑 提交于 2021-02-04 05:04:51

问题


I'm trying to mock a TypeScript class with Jest and I'm obviously doing something because receive the following error:

error TS2743: No overload expects 1 type arguments, but overloads do exist that expect either 0 or 2 type arguments.

This is my code:

Foo.ts

export default class Foo {
  bar(): number {
    return Math.random()
  }
}

Foo.test.ts

import Foo from './Foo'

describe('Foo', () => {
  it("should pass", () => {
    const MockFoo = jest.fn<Foo>(() => ({
      bar: jest.fn(() => {
        return 123
      }),
    }))
  })
})

The full error:

TypeScript diagnostics (customize using `[jest-config].globals.ts-jest.diagnostics` option):
src/Foo.test.ts:6:29 - error TS2743: No overload expects 1 type arguments, but overloads do exist that expect either 0 or 2 type arguments.

6     const MockFoo = jest.fn<Foo>(() => ({
                              ~~~

UPDATE

If it is of any relevance, this is my Jest config:

module.exports = {
  moduleFileExtensions: ['ts', 'js'],
  transform: {
    '^.+\\.ts$': 'ts-jest',
  },
  testMatch: ['**/src/**/*.test.(ts)'],
  testEnvironment: 'node',
};

回答1:


Jest has the following signature for jest.fn:

/**
 * Creates a mock function. Optionally takes a mock implementation.
 */
function fn<T, Y extends any[]>(implementation?: (...args: Y) => T): Mock<T, Y>;

So you need to specify the array of types for the args, in your particular case you could just pass an empty array as there are no args in your implementation function.

const MockFoo = jest.fn<Foo, []>(() => ({



回答2:


As it turns out, it's possible to have the TypeScript compiler ignore errors like this by turning off diagnostics [1].

// jest.config.js
module.exports = {
  // [...]
  globals: {
    'ts-jest': {
      diagnostics: false
    }
  }
};

However, it's currently unclear to me what other implications this might have.

[1] https://huafu.github.io/ts-jest/user/config/diagnostics#enabling-diagnostics-for-test-files-only




回答3:


You can use the ts-jest's mocked() function:

This is all type safe and compiles without warnings in TypeScript:

import Foo from './Foo'
import {mocked} from 'ts-jest/utils'

function argIsFoo(foo : Foo) {
    ; // do nothing
}

describe('Foo', () => {
    it("should pass", () => {
        const mockFoo = mocked({
            bar: jest.fn(() => {
                return 123
            })
        });

        // mockFoo is compatible with Foo class
        argIsFoo(mockFoo);

        // method has the right type
        expect(mockFoo.bar()).toEqual(123);

        // can use the mock in expectations
        expect(mockFoo.bar).toHaveBeenCalled();

        // is type safe access method as a mock
        expect(mockFoo.bar.mock.calls.length).toEqual(1);
    });
});

If you only want to mock out some of Foo's methods, then in mocked() you need to cast your mock object with as unknown as Foo:

import {mocked} from 'ts-jest/utils'

class Foo {
    bar(): number {
        return Math.random();
    }
    dontMockMe(): string {
        return "buzz";
    }
}

function argIsFoo(foo : Foo) {
    ; // do nothing
}

describe('Foo', () => {
    it("should pass", () => {
        const mockFoo = mocked({
            bar: jest.fn(() => {
                return 123
            })
        } as unknown as Foo);

        // mockFoo is compatible with Foo class
        argIsFoo(mockFoo);

        // method has the right type
        expect(mockFoo.bar()).toEqual(123);

        // can use the mock in expectations
        expect(mockFoo.bar).toHaveBeenCalled();

        // is type safe access method as a mock
        expect(mockFoo.bar.mock.calls.length).toEqual(1);
    });
});


来源:https://stackoverflow.com/questions/54941165/jest-mocking-typescript-class-no-overload-expects-1-type-arguments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!