I have a following .ts
module
import client from './client';
export default class DefaultRequest implements IRequest {
make(req: Request): Promise<Response> {
return new Promise<Response>((resolve, reject) => {
client.post(req, (error: Error | null, res: Response) => {
if (error) {
return reject(error);
} else {
return resolve(res);
}
});
});
}
}
I am trying to write a unit test for this class with ts-jest
, so that client
is mocked (and returns some valid Response
).
Here is how I am doing it:
import {mocked} from 'ts-jest/utils';
import client from './client';
import DefaultRequest from './request'
const mockedClient = mocked(client, true);
const testRequest = new DefaultRequest();
jest.mock('./client', () => {
return {
RestClient: jest.fn().mockImplementation(() => {
return {
post: () => {return someValidResponse();},
};
})
};
});
describe('My Tests', () => {
it('Unit Test 1', async () => {
let res: Response = await testRequest.make(buildReq());
});
});
But the mockedClient is still not mocked. This is what ./client.ts
looks like:
import { RestClient } from '@rest/client';
export default new RestClient();
Can the internal client
module that class DefaultRequest
uses be mocked in this manner?
EDIT:
I also tried jest.spyOn
const spiedMethod= jest.spyOn(client, 'post');
const call: Request = new Request();
const response: Response = await call.make(buildRequest());
expect(spiedReleaseMethod).toHaveBeenCalled();
expect(response.getResponsecode()).toBe(200);
And it still calls the original method and not the spied method.
You are testing the request.ts
module that depends on the client.ts
module. So you need to mock the client.ts
module and its post
method rather than the @rest/client
package.
E.g.
request.ts
:
import client from './client';
interface IRequest {
make(req: Request): Promise<Response>;
}
export default class DefaultRequest implements IRequest {
make(req: Request): Promise<Response> {
return new Promise<Response>((resolve, reject) => {
client.post(req, (error: Error | null, res: Response) => {
if (error) {
return reject(error);
} else {
return resolve(res);
}
});
});
}
}
client.ts
: (No matter what package implementation client uses, as long as the interfaces exposed by the module are the same)
export default {
post(req, callback) {
console.log('real implementation');
},
};
request.test.ts
:
import { mocked } from 'ts-jest/utils';
import client from './client';
import DefaultRequest from './request';
jest.mock('./client');
const mockedClient = mocked(client);
describe('68115300', () => {
afterAll(() => {
jest.resetAllMocks();
});
it('should pass', () => {
mockedClient.post.mockImplementationOnce((req, callback) => {
callback(null, 'mocked response');
});
const testRequest = new DefaultRequest();
testRequest.make(('req' as unknown) as Request);
expect(mockedClient.post).toBeCalledWith('req', expect.any(Function));
});
});
test result:
PASS examples/68115300/request.test.ts (12.448 s)
68115300
✓ should pass (3 ms)
------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------|---------|----------|---------|---------|-------------------
All files | 77.78 | 50 | 75 | 77.78 |
client.ts | 50 | 100 | 0 | 50 | 3
request.ts | 85.71 | 50 | 100 | 85.71 | 12
------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 14.61 s