The documentation says:
Supports automatic of jest.mock() calls
However, when it is used, the auto-mocked class' type signature isn't updated with the jest mock extensions, which results in errors like:
error TS2339: Property 'mockClear' does not exist on type 'typeof TokenRepository'.
The only "simple" work around I've found is to typecast the mocked class as a jest.Mock like:
(TokenRepository as jest.Mock<TokenRepository>).mockClear();
Ideally provide some way to update the type definitions of auto-mocked classes.
If that's not possible, then at least update the documentation to call out this limitation and provide samples of how to work around it.
I'm not sure it's possible to automatically cast the class - if it is, it's beyond my typescript-fu.
Definitely agree the documentation could be clearer. Would love a PR
Badly it's not possible to dynamically update a class like that. Modules could be overridden, but knowing their path and the overrides can only be written with static strings. So here it's the documentation that should be updated, nothing can be done code-wise.
_example override of a module (I might be wrong at module file location, it's just an example):_
import Vue from 'vue' // so that existing types aren't erased by our override
declare module 'vue/types' { // <== this issue would need this string to be dynamic
interface VueConstructor { // already declared in 'vue/types.d.ts' package's file
myProp: string // added prop
}
}
A possible way of doing so (but I did not check and anyway it would be a big feature) is by creating a ts-server plugin.......
Can't do this by a language service plugin. Nothing even a lang service plugin can change the typing of an import, neither of a var. That is why I chose the helper way to fix this, see the PR
I fell down an internet hole for hours trying to figure this one out. Glad I found this thread!
For anyone else that ends up here, I refer you to mocked()
e.g.
import { mocked } from 'ts-jest/utils';
import { thingThatCallsMyFunc } from './ThingUnderTest'; // <-- this is the item under test
import { myFunc } from './MyDependency'; // <-- this is the dependecy we're mocking
jest.mock('./MyDependency'); // <-- gotta declare the module as mocked up here
describe('a test', () => {
test('my test 1', () => {
// and override the mocked behaviour down here
mocked(myFunc).mockImplementation(() => true); // <-- because myFunc.mockImplementation(...) can't be done in typescript
expect(thingThatCallsMyFunc.doSomething()).toBe(true);
});
test('my test 2', () => {
mocked(myFunc).mockImplementation(() => false); // <-- different mock implementations per test
expect(thingThatCallsMyFunc.doSomething()).toBe(false);
});
})
same issue. When call .mockClear method, got tsc error:
Property 'mockClear' does not exist on type 'typeof LocationDAOImpl'.
This doesn't work for classes
TypeScript diagnostics (customize using `[jest-config].globals.ts-jest.diagnostics` option):
src/services/message-service.test.ts:9:3 - error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'typeof import("D:/coding/reddit-chaser/node_modules/ts-jest/dist/index")' has no compatible call signatures.
Example. Snoowrap is a class that I'm trying to mock. It's a class with a constructor, not an instance.
import Snoowrap = require("snoowrap")
jest.mock("snoowrap")
beforeEach(() => {
var myMockClass = mocked(Snoowrap) // this generates the above error before I'm even able to mock it
})
This works, but then no typings are available:
import Snoowrap from "snoowrap"
const mockComposeMessage = jest.fn()
jest.mock("snoowrap", () => {
return jest.fn().mockImplementation(() => ({
composeMessage: mockComposeMessage
}))
})
chai.should()
beforeEach(() => {
mockComposeMessage.mockClear()
})
Referring to the docs here works great for javascript, but I can't figure this out at all for typescript
mocked(myImportedModuleMethod).mockClear() works
I fell down an internet hole for hours trying to figure this one out. Glad I found this thread!
For anyone else that ends up here, I refer you to mocked()
e.g.
import { mocked } from 'ts-jest/utils'; import { thingThatCallsMyFunc } from './ThingUnderTest'; // <-- this is the item under test import { myFunc } from './MyDependency'; // <-- this is the dependecy we're mocking jest.mock('./MyDependency'); // <-- gotta declare the module as mocked up here describe('a test', () => { test('my test 1', () => { // and override the mocked behaviour down here mocked(myFunc).mockImplementation(() => true); // <-- because myFunc.mockImplementation(...) can't be done in typescript expect(thingThatCallsMyFunc.doSomething()).toBe(true); }); test('my test 2', () => { mocked(myFunc).mockImplementation(() => false); // <-- different mock implementations per test expect(thingThatCallsMyFunc.doSomething()).toBe(false); }); })
this works perfect with react-boilerplate-typescript. thanks, man
mocked is a pretty good solution. Another one is https://github.com/userlike/joke, if you are using babel to do some transforms already.
mockedis a pretty good solution. Another one is https://github.com/userlike/joke, if you are using babel to do some transforms already.
After 2 days of all sorts of gymnastics this one worked in a few minutes for me. Thanks for suggesting!
I fell down an internet hole for hours trying to figure this one out. Glad I found this thread!
For anyone else that ends up here, I refer you to mocked()
e.g.
import { mocked } from 'ts-jest/utils'; import { thingThatCallsMyFunc } from './ThingUnderTest'; // <-- this is the item under test import { myFunc } from './MyDependency'; // <-- this is the dependecy we're mocking jest.mock('./MyDependency'); // <-- gotta declare the module as mocked up here describe('a test', () => { test('my test 1', () => { // and override the mocked behaviour down here mocked(myFunc).mockImplementation(() => true); // <-- because myFunc.mockImplementation(...) can't be done in typescript expect(thingThatCallsMyFunc.doSomething()).toBe(true); }); test('my test 2', () => { mocked(myFunc).mockImplementation(() => false); // <-- different mock implementations per test expect(thingThatCallsMyFunc.doSomething()).toBe(false); }); })
For people still ending up here, this works for me without the need for mocked()
import { SomeClass } from './class-file';
jest.mock('./class-file');
describe('test', () => {
const object = new SomeClass();
test('first test', () => {
object.get = jest.fn(() => null);
// ...
});
test('second test', () => {
object.get = jest.fn(() => 'blabla');
object.save = jest.fn(() => { id: 1 });
// ...
});
});
I just can't find a way to do SomeClass.mockClear(); because tsc will complain that mockClear does not exist.
Most helpful comment
I fell down an internet hole for hours trying to figure this one out. Glad I found this thread!
For anyone else that ends up here, I refer you to mocked()
e.g.