Reputation: 464
New to Jest so I'm wanting to understand an issue I'm having a bit better. I'm trying to test an implementation of a class in Jest but it's complaining that my function "is not a function"
Typescript Service:
export class TestService {
constructor() { }
getAllData = async (): Promise<any> => {
return { id: '1', name: 'test' }
}
}
Test
import { TestService } from '../TestService';
describe('TestService', async () => {
const service = new TestService();
const res = await service.getAllData();
....
}
jest.config.ts import type {Config} from '@jest/types';
const config: Config.InitialOptions = {
roots:['<rootDir>'],
testMatch: [
'**/__tests__/**/*.+(ts|tsx|js)',
'**/?(*.)+(spec|test).+(ts|tsx|js)'
],
testPathIgnorePatterns: ['dist', 'node_modules'],
transform: {"\\.(ts|tsx)$": "ts-jest"},
verbose: true,
preset: 'ts-jest',
testEnvironment: 'node',
collectCoverage: true,
automock: true
};
export default config;
When I run the tests, Jest is throwing an error that says "service.getAllData is not a function". Everything I could find online points me to mocks but I wouldn't think I would want to mock this as I want to test the actual implementation of the class; I assume I'd want to mock any external functions within getAllData()
.
I have a controller that is able to call this function with no problems so I'm wondering if either 1) there's some other way this must be called or 2) Jest essentially requires mocks of some kind.
Please let me know if you have any insight
Thanks!
Upvotes: 2
Views: 2234
Reputation: 223318
automock
is a bad practice and should be preferably disabled. In case a module needs to be automatically mocked, this can be done explicitly with jest.mock
. Manual mocks are preferable most times because they result in explicitly specified implementations that should be additionally provided to auto-mocks, too.
Jest auto-mocking is undocumented, it results in poorly understood magic that may not meet the expectations of a developer and may change without notice in next Jest versions. Class auto-mocking is briefly described in the guide. getAllData
is instance method that is created inside a constructor. Jest auto-mocking relies on runtime contents of a module and checks static and prototype members, there's no way how it could process a constructor.
In order to be detected by Jest auto-mocking, getAllData
should be prototype method, this is also suggested by common sense because there are no reasons for it to be an arrow:
export class TestService {
getAllData(): Promise<any> {
return { id: '1', name: 'test' }
}
}
Auto-mocking doesn't result in a correct mock because the method is stubbed it doesn't return a promise. The problem could be determined at earlier point because auto-mocks require an implementation to be specified, this wasn't done in the OP:
const service = new TestService();
service.getAllData.mockResolvedValueOnce(...);
...
For prototype methods this can be done before an instance is available:
TestService.prototype.getAllData.mockResolvedValueOnce(...);
const service = new TestService();
...
Upvotes: 1