问题
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