yeahoffline / redis-mock

Node.js redis client mock
213 stars 111 forks source link

TypeError: this.redis.time is not a function #170

Open chamikabm opened 3 years ago

chamikabm commented 3 years ago

I try to mock the redis using the library with "rsmq" [https://www.npmjs.com/package/rsmq] with jest as follows, but gives me an error:

My packge.json

"jest": {
    "testEnvironment": "node",
    "setupFilesAfterEnv": [
      "./jest.setup.redis-mock.js"
    ]
  } 

jest.setup.redis-mock.js File: jest.mock('redis',() => jest.requireActual('redis-mock'));

Usage:

const redis = require('redis');
const client = redis.createClient({ host: process.env.REDIS_HOST, port: process.env.REDIS_PORT, realtime: true });
const rsmq = new RedisSMQ({ client, ns: "rsmq" });
rsmq.createQueue({ qname: "errors" }, function (err, resp) {
    if (err) {
        console.log(err)
    }

    if (resp === 1) {
        console.log("queue created", "errors")
    }
});

RSMQ library referenfe to redis.time function (This is where the error throws when running the test suite.):

this.createQueue = (options, cb) => {
            const key = `${this.redisns}${options.qname}:Q`;
            options.vt = options.vt != null ? options.vt : 30;
            options.delay = options.delay != null ? options.delay : 0;
            options.maxsize = options.maxsize != null ? options.maxsize : 65536;
            if (this._validate(options, ["qname", "vt", "delay", "maxsize"], cb) === false)
                return;
            this.redis.time((err, resp) => {
                if (err) {
                    this._handleError(cb, err);
                    return;
                }

Error message on console when running the test suite:

            this.redis.time((err, resp) => {
                       ^

TypeError: this.redis.time is not a function
    at RedisSMQ.createQueue
kamiljano commented 3 years ago

yes. You'll find that there are quite a few functions in the mock that are not currently supported. Sorry about that. Then again adding the support for this method should be rather straight forward. Perhaps you would be willing to submit your own PR? If not, I'll take care of it as soon as I can, but that might take a week or two

chamikabm commented 3 years ago

If you can provide me a guide line on how to do it, Yeah I should be able to do it.

kamiljano commented 3 years ago

heh... i just wrote a test to see how much the mock is actually missing and the result is terrifying... we're missing the support for 262 functions. At this point adding the support for TIME is probably not gonna cut it...

kamiljano commented 3 years ago

done. Released in version 0.56.1

chamikabm commented 3 years ago

hahaha, Interesting. Superb stuff! Thanks for the fix.

chamikabm commented 3 years ago

@kamiljano Sorry to disturb you again. I noticed that this rsmq node library using more redis functions other than above time that have not mocked yet.

multi
evalsha
sadd
script
smembers
kamiljano commented 3 years ago

Hmm... I know without even looking that sadd and multi are there. I guess I'll try to drop your code sample into a test and see what happens

chamikabm commented 3 years ago

Yeah sure. This is the library that uses with the Redis instance. https://www.npmjs.com/package/rsmq.

So basically I need to mock the Redis in order to work with all the functions that have exposed with the above rsmq npm module. In my case following what I'm doing in order to interact with the rsmq using redis client.

const RedisSMQ = require("rsmq");
const redis = require('redis');
const client = redis.createClient({ host: process.env.REDIS_HOST, port: process.env.REDIS_PORT, auth_pass: process.env.REDIS_PASSWORD,, realtime: true });
var axios = require('axios');

const rsmq = new RedisSMQ({ client, ns: "rsmq" });

rsmq.createQueue({ qname: "errors" }, function (err, resp) {
    if (err) {
        console.log(err)
    }

    if (resp === 1) {
        console.log("queue created", "errors")
    }
});

async function makeQueue(res, qname,vt,delay,maxsize) {
    rsmq.createQueue({ qname,vt,delay,maxsize }, function (err, resp) {
        if (err) {
            console.error(err)
            return res.send("Error in creating" + qname)
        }

        if (resp === 1) {
            console.log("queue created", qname)
            return res.send('Hello world' + qname)
        }
    });
}
async function deleteQueue(res, qname) {
    rsmq.deleteQueue({ qname }, function (err, resp) {
        if (err) {
            console.error(err)
            return res.send("error")
        }

        if (resp === 1) {
            return res.send("Queue and all messages deleted.")
        } else {
            return res.send("Queue not found.")
        }
    })

}
async function listQueues(res) {
   rsmq.listQueues(function (err, queues) {
        if (err) {
            console.error(err)
            return
        }

       return res.send("Active queues: " + queues.join(","))

    });
}
async function setQueueAttributes(res, qname,vt,delay,maxsize) {
    rsmq.setQueueAttributes({ qname,vt,delay,maxsize }, function (err, resp) {
        if (err) {
            console.error(err);
            return res.send("error");
        }

        return res.send(JSON.stringify(resp))
    });
}
async function getQueueAttributes(res,qname){
    rsmq.getQueueAttributes({ qname }, function (err, resp) {
        if (err) {
            console.error(err);
            return res.send("error");
        }

        return res.send(JSON.stringify(resp))
    });
}
async function postMessage(res,qname,message) {
    rsmq.sendMessage({ qname, message}, function (err, resp) {
        if (err) {
            console.error(err)
            return res.send("error")
        }
        console.log("Message sent. ID:", resp);
        return res.send(JSON.stringify(resp))
    });
}
async function getMessage(res,qname) {
    rsmq.receiveMessage({ qname}, function (err, resp) {
        if (err) {
            console.error(err)
            return res.send("error")
        }

        if (resp.id) {
            return res.send(JSON.stringify(resp))
        } else {
            return res.send("No messages for me...")
        }
    });
}
async function getAndDeleteMessage(res,qname) {
    rsmq.popMessage({ qname }, function (err, resp) {
        if (err) {
            console.error(err)
            return res.send("error")
        }

        if (resp.id) {
            console.log("Message received and deleted from queue", resp)
            return res.send(JSON.stringify(resp))
        } else {
            return res.send("No messages for me...")
        }
    });
}

async function queueWorker(qname) {
    const RSMQWorker = require("rsmq-worker");
    const worker = new RSMQWorker(qname, { redis: client });
    var rsmq = worker._getRsmq();

        worker.on( "message", function( msg, next, id ){
        // process your message
        console.log("Message id : " + id);
            console.log(msg);
            let {data, url,method,headers} = JSON.parse(msg)
            var config = {
            method,
            url,
            headers,
            data
            };

            axios(config)
                .then(function (response) {
                console.log(response.status)
            // console.log(JSON.stringify(response.data));
            })
            .catch(function (error) {
                console.error(error.response.status, error.response.statusText);
                rsmq.sendMessage({ qname:"errors", message:JSON.stringify({code:error.response.status,status:error.response.statusText,original: msg})}, function (err, resp) {
                    if (err) {
                        console.error(err)
                    }
                    console.log("Message sent. ID:", resp);
                });
            }).then(function() {
                    next();
                });
    });

    // optional error listeners
    worker.on('error', function( err, msg ){
        console.error( "ERROR", err, msg.id );
    });
    worker.on('exceeded', function( msg ){
        console.warn( "EXCEEDED", msg.id );
    });
    worker.on('timeout', function( msg ){
        console.warn( "TIMEOUT", msg.id, msg.rc );
    });

    worker.start();
}

module.exports = {
    makeQueue,
    listQueues,
    setQueueAttributes,
    getQueueAttributes,
    deleteQueue,
    postMessage,
    getMessage,
    getAndDeleteMessage,
    queueWorker
}
kamiljano commented 3 years ago

i want you to know that I started looking into your problem. I imported rsmq into tests (not yet committed... because they all fail...) and started checking the commands that it tries to issue in the background: https://github.com/yeahoffline/redis-mock/pull/175 but man... this library injects custom LUA scripts into redis. This will require some major hacking to mock it... you're not giving me a very easy task :P

chamikabm commented 3 years ago

hahaha, yeah I know. Happy coding.