I'm using ioredis
npm library in my production code :
file: redisManager.ts
import Redis from 'ioredis';
import EventEmitter from "events";
import {Logger} from "@aws-lambda-powertools/logger";
const logger: Logger= new Logger({serviceName: 'redisManager'});
export class RedisManager extends EventEmitter {
protected readonly redisClient: Redis;
constructor() {
super();
this.redisClient = new Redis(Number(process.env.REDIS_PORT), process.env.REDIS_HOST);
this.redisClient.on('error', err => {
logger.error(`Got an error from Redis: ${err.message}`);
this.emit('error', err);
});
}
getRedisClient(): Redis {
return this.redisClient;
}
waitForRedisConnection = (): Promise<void> => {
return new Promise<void>((resolve, reject) => {
this.redisClient.on('connect', () => logger.info(`Got "connect" event from Redis. Stream is connected to the server`));
this.redisClient.on('ready', () => {
logger.info(`Got "ready" event from Redis. Connection established.`);
resolve();
});
this.redisClient.on('error', async (err) => {
logger.error(`Got "error" event from Redis. Details: [${err.message}]`);
reject(err);
});
});
}
async addKey(redisKey : string, ttl: number) {
return this.redisClient.set(redisKey, 'The value', "PX", ttl);
}
}
export async function getRedisManager(): Promise<RedisManager> {
try {
const redisManager = new RedisManager();
await redisManager.waitForRedisConnection();
} catch (err) {
logger.error(`Get Redis manager failed with error: ${err.message}`);
throw err;
}
}
}
file app.ts
export const lambdaHandler = async (event: SQSEvent, context: Context): Promise<SQSBatchResponse> => {
context.callbackWaitsForEmptyEventLoop = false;
const batchFailures: SQSBatchResponse = {
"batchItemFailures": []
};
try {
const redisManager: RedisManager = await getRedisManager();
await Promise.all(event.Records.map(async (sqsRecord: SQSRecord) => {
try {
const settingConfig = JSON.parse(sqsRecord.body) as SettingsConfig;
await redisManager.addKey(settingConfig, 333333);
} catch (e) {
const error = e as Error;
logger.error(`Lambda failed. on messageId=${sqsRecord.messageId}: ${error.message}`);
batchFailures.batchItemFailures.push({itemIdentifier: sqsRecord.messageId})
}
}));
logger.info(SUCCESS_MESSAGE);
} catch (e) {
const error = e as Error;
logger.error(`Lambda execution failed. Got error: ${error.message}`);
throw error;
} finally {
logger.info(JSON.stringify(batchFailures, null, 2));
return batchFailures;
}
};
I want to simulate connection failure while connecting to Redis via jest.
import {beforeAll, beforeEach, describe, expect, it, jest} from '@jest/globals';
import RedisMock from 'ioredis-mock';
import Redis from "ioredis";
jest.mock('ioredis', () => jest.requireActual('ioredis-mock'));
describe('lambdaHandler()', () => {
it('Redis connection fail ', async () => {
const result: SQSBatchResponse = await lambdaHandler(sqsTriggerEvent, CONTEXT);
}
}
How do I make redisClient.on('error')
to be triggered, in unit test?
Note: In all other tests to simulate get and set from Redis I'm using ioredis-mock
and it works perfectly.