I have a task to test gRPC client call functions with Jest. Here is what a typical node.js function looks like:
client.authenticate(request, meta, (error, response) => {
if (!error) {
console.log('REPLY FROM SERVER: ', response)
} else {
console.error(error)
}
})
Procedure calls are callback functions, as we see I can not export response object to outside variable. The above function is the one I need to test. I need to check if the function has been called with no error. How do I do it with jest? Been struggling for a while now.
You can use jest.spyOn(object, methodName) to mock client.authenticate
.
E.g.
index.ts
:
import { client } from './client';
export function main() {
const request = {};
const meta = {};
client.authenticate(request, meta, (error, response) => {
if (!error) {
console.log('REPLY FROM SERVER: ', response);
} else {
console.error(error);
}
});
}
client.ts
:
export const client = {
authenticate(request, meta, callback) {
console.log('real implementation');
},
};
index.test.ts
:
import { main } from './';
import { client } from './client';
describe('62214949', () => {
it('should log correct response', () => {
const mResponse = 'mocked response';
const logSpy = jest.spyOn(console, 'log');
jest.spyOn(client, 'authenticate').mockImplementationOnce((request, meta, callback) => {
console.log('mocked implementation');
callback(null, mResponse);
});
main();
expect(logSpy).toBeCalledWith('REPLY FROM SERVER: ', 'mocked response');
expect(client.authenticate).toBeCalledWith({}, {}, expect.any(Function));
});
it('should handle error', () => {
const mError = new Error('network');
const logSpy = jest.spyOn(console, 'error');
jest.spyOn(client, 'authenticate').mockImplementationOnce((request, meta, callback) => {
console.log('mocked implementation');
callback(mError);
});
main();
expect(logSpy).toBeCalledWith(mError);
expect(client.authenticate).toBeCalledWith({}, {}, expect.any(Function));
});
});
unit test result with coverage report:
PASS stackoverflow/62214949/index.test.ts (10.557s)
62214949
✓ should log correct response (23ms)
✓ should handle error (8ms)
console.log
mocked implementation
at CustomConsole.<anonymous> (node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866:25)
console.log
REPLY FROM SERVER: mocked response
at CustomConsole.<anonymous> (node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866:25)
console.log
mocked implementation
at CustomConsole.<anonymous> (node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866:25)
console.error
Error: network
at Object.<anonymous> (/Users/ldu020/workspace/github.com/mrdulin/react-apollo-graphql-starter-kit/stackoverflow/62214949/index.test.ts:18:20)
at Object.asyncJestTest (/Users/ldu020/workspace/github.com/mrdulin/react-apollo-graphql-starter-kit/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:100:37)
at resolve (/Users/ldu020/workspace/github.com/mrdulin/react-apollo-graphql-starter-kit/node_modules/jest-jasmine2/build/queueRunner.js:45:12)
at new Promise (<anonymous>)
at mapper (/Users/ldu020/workspace/github.com/mrdulin/react-apollo-graphql-starter-kit/node_modules/jest-jasmine2/build/queueRunner.js:28:19)
at promise.then (/Users/ldu020/workspace/github.com/mrdulin/react-apollo-graphql-starter-kit/node_modules/jest-jasmine2/build/queueRunner.js:75:41)
at process._tickCallback (internal/process/next_tick.js:68:7)
8 | console.log('REPLY FROM SERVER: ', response);
9 | } else {
> 10 | console.error(error);
| ^
11 | }
12 | });
13 | }
at CustomConsole.<anonymous> (node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866:25)
at stackoverflow/62214949/index.ts:10:15
at Object.<anonymous> (stackoverflow/62214949/index.test.ts:22:7)
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------|---------|----------|---------|---------|-------------------
All files | 90 | 100 | 66.67 | 90 |
client.ts | 50 | 100 | 0 | 50 | 3
index.ts | 100 | 100 | 100 | 100 |
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 12.424s