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.
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.
Share Improve this question edited Jun 5, 2020 at 12:31 Aika Sat asked Jun 5, 2020 at 12:04 Aika SatAika Sat 1813 silver badges12 bronze badges 1- If you want to test this end-to-end, you would need to have Jest check your console to see if 'REPLY FROM SERVER' has been printed or not, as that's the only thing visible to the user after this function is called. – Sean Chapman Commented Sep 18, 2020 at 8:42
3 Answers
Reset to default 5You 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./mrdulin/react-apollo-graphql-starter-kit/stackoverflow/62214949/index.test.ts:18:20)
at Object.asyncJestTest (/Users/ldu020/workspace/github./mrdulin/react-apollo-graphql-starter-kit/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:100:37)
at resolve (/Users/ldu020/workspace/github./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./mrdulin/react-apollo-graphql-starter-kit/node_modules/jest-jasmine2/build/queueRunner.js:28:19)
at promise.then (/Users/ldu020/workspace/github./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
I got a very similar problem: we use Cypress to test a React App which uses GRPC-Web protocol to municate with GRPC backends.
Almost every library out there to mock GRPC backends requires starting a full server along with your testing suite, which is pretty inconvenient and annoying in CI environments.
So I decided to make a small package that stimulates the part of the backend network which is responsible for encoding responses for gRPC-web clients. We use it in bination with Cypress and its network interception feature. So we can intercept a GRPC call and inject a mocked response during E2E tests.
https://www.npmjs./package/@botchris/grpc-web-mock
try this git mock repo, it provides mock responses. U need to create mock grpc server and add rpc method from the proto file. you can provide your actual responses in rules. grpc-mock