I use ts-jest
and jest
to write my testing files with typescript.
I am confused how to typing the mock function of a module.
Here is my code:
./module.ts
:
import {IObj} from '../interfaces';
const obj: IObj = {
getMessage() {
return `Her name is ${this.genName()}, age is ${this.getAge()}`;
},
genName() {
return 'novaline';
},
getAge() {
return 26;
}
};
export default obj;
./module.test.ts
:
import * as m from './module';
describe('mock function test suites', () => {
it('t-1', () => {
// I think the jest.Mock<string> type here is not correct.
m.genName: jest.Mock<string> = jest.fn(() => 'emilie');
expect(jest.isMockFunction(m.genName)).toBeTruthy();
expect(m.genName()).toBe('emilie');
expect(m.getMessage()).toEqual('Her name is emilie, age is 26');
expect(m.genName).toHaveBeenCalled();
});
});
how to type the mock function genName
of module m
?
typescript
give me an error here:
Error:(8, 7) TS2540:Cannot assign to 'genName' because it is a constant or a read-only property.
I use ts-jest
and jest
to write my testing files with typescript.
I am confused how to typing the mock function of a module.
Here is my code:
./module.ts
:
import {IObj} from '../interfaces';
const obj: IObj = {
getMessage() {
return `Her name is ${this.genName()}, age is ${this.getAge()}`;
},
genName() {
return 'novaline';
},
getAge() {
return 26;
}
};
export default obj;
./module.test.ts
:
import * as m from './module';
describe('mock function test suites', () => {
it('t-1', () => {
// I think the jest.Mock<string> type here is not correct.
m.genName: jest.Mock<string> = jest.fn(() => 'emilie');
expect(jest.isMockFunction(m.genName)).toBeTruthy();
expect(m.genName()).toBe('emilie');
expect(m.getMessage()).toEqual('Her name is emilie, age is 26');
expect(m.genName).toHaveBeenCalled();
});
});
how to type the mock function genName
of module m
?
typescript
give me an error here:
Share Improve this question edited Dec 6, 2018 at 4:27 Lin Du asked Jul 6, 2017 at 6:52 Lin DuLin Du 102k134 gold badges332 silver badges561 bronze badgesError:(8, 7) TS2540:Cannot assign to 'genName' because it is a constant or a read-only property.
6 Answers
Reset to default 19This is how I have solved the same problem and how I do all of my mocking and spying now.
import * as m from './module';
describe('your test', () => {
let mockGenName;
beforeEach(() => {
mockGenName = jest.spyOn(m,
'genName').mockImplemetation(() => 'franc');
})
afterEach(() => {
mockGenName.mockRestore();
})
test('your test description', () => {
// do something that calls the genName function
expect(mockGenName).toHaveBeenCalledTimes(1);
})
})
With this setup, you can programmatically change the implementation of the mock for different tests, and then assert that the function was called and what it was called with, all while clearing your mock in between tests and after all tests.
Try this one - https://jestjs.io/docs/mock-function-api#typescript
In short there are only three strategies possible
- Mock the entire module being imported and get handler to the mocked function to manipulate it (jest.Mock(), jest.MockedFunction)
- Mock the module partially being imported and get handler to the mocked function to manipulate it (jest.Mock() with factory, jest.MockedFunction)
- Import the module as is and then spy on the function which needs to be mocked (jest.spy())
You want to mock the module and then alter the exported function within it. This should replace your import statement.
jest.mock('./module', () => ({
genName: jest.fn().mockImplementation(() => 'emilie')
}))
The reason why I got the error is:
The properties of a module object foo (import * as foo from 'foo') are like the properties of a frozen object.
For more info, see In ES6, imports are live read-only views on exported values
When I changed import * as m from './module'
to import m from './module';
, The error is gone.
Package versions:
"typescript": "^3.6.4"
"ts-jest": "^24.1.0"
"jest": "^24.9.0",
jest.config.js
:
module.exports = {
preset: 'ts-jest/presets/js-with-ts',
//...
}
tsconfig.json
:
"compilerOptions": {
"target": "es6",
"module": "commonjs",
//...
}
import * as m from './module'
jest.mock('./module', () => ({
genName: jest.fn().mockImplementation(() => 'emilie')
// will return "enilie" for all tests
}))
it('returns franc', () => {
m.genName.mockImplementationOnce(() => 'franc')
// will return "franc" for this particular test
})
I'm mocking it a follow :
jest.mock('./module')
const {genName} = require('./module')
and in my test :
genName.mockImplementationOnce(() => 'franc')
works great for me and no typescript errors