Open fishcharlie opened 2 years ago
Curious about this as well. Experiencing the same behavior.
any updates on this one? this actually prevents my from using this package
It's because redis-mock only supports the callback syntax for redis not async/await, which was removed in the latest major version of the redis package. This works:
let redis = require('redis-mock').createClient()
await new Promise<void>((resolve) => {
redis.set('foo', 'bar', () => {
log('set complete')
redis.get('foo', (err, val) => {
log('get complete', val)
resolve()
})
})
})
and as an aside, the latest version of @types/redis-mock is incorrect.
Here's a kind of smelly workaround:
let redis = require('redis-mock').createClient()
redis.set = promisify(redis.set.bind(redis))
redis.get = promisify(redis.get.bind(redis))
await redis.set('foo', 'bar')
log('set complete')
let val = await redis.get('foo')
log('get complete', val)
Building from @rbrcurtis 's workaround:
I had to create a custom promisify function for the set method to be able to pass additional args, for example client.set("key", "value", {EX: ttl})
.
Because this library has a set method where the last argument is not actually the callback, but args = {}
, this was required to be able to pass additional args and it not throw.
I'm sure there are better ways to do this (l couldn't get util/promisify custom to work), and this now means I can't mock ttl, but this at least got me started.
I put this all in jest setup file:
import util from 'node:util';
jest.mock('redis', () => jest.requireActual('redis-mock'));
beforeAll(() => {
let redis = require('./server/lib/redis/client').redisClient;
redis.set = customPromisify(redis.set.bind(redis));
redis.get = util.promisify(redis.get.bind(redis));
});
function customPromisify(f) {
return function (...args) {
args.pop(); // just removing the last argument basically
return new Promise((resolve, reject) => {
function cb(err, result) {
if (err) {
reject(err);
} else {
resolve(result);
}
}
args.push(cb);
f.call(this, ...args);
});
};
}
Building from @rbrcurtis 's workaround:
I had to create a custom promisify function for the set method to be able to pass additional args, for example
client.set("key", "value", {EX: ttl})
.Because this library has a set method where the last argument is not actually the callback, but
args = {}
, this was required to be able to pass additional args and it not throw.I'm sure there are better ways to do this (l couldn't get util/promisify custom to work), and this now means I can't mock ttl, but this at least got me started.
I put this all in jest setup file:
import util from 'node:util'; jest.mock('redis', () => jest.requireActual('redis-mock')); beforeAll(() => { let redis = require('./server/lib/redis/client').redisClient; redis.set = customPromisify(redis.set.bind(redis)); redis.get = util.promisify(redis.get.bind(redis)); }); function customPromisify(f) { return function (...args) { args.pop(); // just removing the last argument basically return new Promise((resolve, reject) => { function cb(err, result) { if (err) { reject(err); } else { resolve(result); } } args.push(cb); f.call(this, ...args); }); }; }
@eatoncw The customPromisify function should have a check for args length in case redis.set
is called without the additional args. Something like this:
if (args.length > 2)
args.pop();
The following code should print
bar
to the console. However, instead it printsundefined
.Running redis-mock version
0.56.3
.