Reputation: 2064
// client.js
const getCacheClient = async (configuration) => {
return new Promise((resolve, reject) => {
const redisClient = redis.createClient(configuration.port, configuration.host);
// note that promise is fullfiled or rejected based on redis client events
redisClient.on('ready', () => resolve(redisClient));
redisClient.on('error', (redisError) => {
console.log('Error connecting Redis', redisError.message);
redisClient.quitAsync();
return reject(redisError);
});
});
};
What is the proper way of testing a Redis client that is returned by a promise but the resolve or reject is based on an event handler?
Since the resolve or reject are based on the event of "success/error" I´m not sure how to recreate the events. I´m getting an 'Async callback was not invoked within the 10000 ms timeout specified by jest.setTimeout.Timeout - Async callback was not invoked within the 10000 ms timeout specified by jest.setTimeout.Error:'
// client.test.js
import client, { __RewireAPI__ as API } from '../client';
describe('get-cache-client', () => {
const mockBlueprint = { promisifyAll: jest.fn((x) => x) };
const mockRedisClient = {
getAsync: jest.fn(),
setexAsync: jest.fn(),
on: jest.fn(),
};
const mockRedis = {
createClient: {
on: jest.fn(),
},
};
beforeEach(() => {
API.__Rewire__('redis', mockRedis);
API.__Rewire__('blueprint', mockBlueprint);
});
afterEach(() => {
__rewire_reset_all__();
mockRedis.createClient.mockReset();
});
describe('getCacheClient', () => {
it('should create a client with the expected parameters', async (done) => {
const config = {
host: 'testrediscachehost',
port: 1234,
key: 'testrediscachekey',
};
mockRedis.createClient.on.mockReturnValue(mockRedisClient);
const client = await expect(getCacheClient(config));
// it gets stuck here, promise is never fulfilled or rejected
// .... tests...
});
});
});
Upvotes: 0
Views: 2577
Reputation: 102277
I didn't see any reason to use __Rewire__
things.
Use jest.spyOn()
and jest.restoreAllMocks()
are enough.
E.g.
client.js
:
import redis from 'redis';
export const getCacheClient = async (configuration) => {
return new Promise((resolve, reject) => {
const redisClient = redis.createClient(configuration.port, configuration.host);
redisClient.on('ready', () => resolve(redisClient));
redisClient.on('error', (redisError) => {
console.log('Error connecting Redis', redisError.message);
redisClient.quit();
return reject(redisError);
});
});
};
client.test.js
:
import { getCacheClient } from './client';
import redis from 'redis';
describe('68492493', () => {
afterEach(() => {
jest.restoreAllMocks();
});
test('should create redis client and be ready', async () => {
const config = {
host: 'testrediscachehost',
port: 1234,
key: 'testrediscachekey',
};
const mRedisClient = {
on: jest.fn().mockImplementation(function (event, handler) {
if (event === 'ready') {
handler();
}
return this;
}),
quit: jest.fn(),
};
const createClientSpy = jest.spyOn(redis, 'createClient').mockReturnValueOnce(mRedisClient);
await getCacheClient(config);
expect(createClientSpy).toBeCalledWith(1234, 'testrediscachehost');
expect(mRedisClient.on).toBeCalledWith('ready', expect.any(Function));
});
test('should handle error', async () => {
// Try test by yourself
});
});
test result:
PASS examples/68492493/client.test.ts (8.739 s)
68492493
✓ should create redis client and be ready (4 ms)
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------|---------|----------|---------|---------|-------------------
All files | 75 | 100 | 80 | 66.67 |
client.ts | 75 | 100 | 80 | 66.67 | 8-10
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 9.548 s, estimated 10 s
Ran all test suites related to changed files.
Upvotes: 1