Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stubbing Redis interactions in javascript using Sinon

I am working in node.js. My app interacts with Redis via the node_redis module. I'm using mocha and sinon to automate testing of my app. My app looks something like this:

...snip
var redisClient = redis.createClient(redisPort, redisHost);
var someValue = redisClient.get("someKey");
return someValue;
....

I want to stub the call to redisClient.get(). To do this I also need to stub the call to redis.createClient() - I think... Here's my test code:

...
var redis = require("redis");
var redisClient;
...
sinon.stub(redisClient, 'get').returns("someValue");
sinon.stub(redis, "createClient").returns(redisClient);
...
assert.equal(redis_client_underTest.call_to_redis(), "someValue");
...

The test fails with AssertionError: false == "someValue"

How do I stub out redisClient, or is this even possible?

like image 537
Rich Avatar asked Jul 24 '14 14:07

Rich


People also ask

How do you mock Redis with Sinon?

var redis = require("redis"); var fakeredis = require('fakeredis'); var sinon = require('sinon'); var assert = require('chai'). assert; var users, client; describe('redis', function(){ before(function(){ sinon. stub(redis, 'createClient', , fakeredis. createClient); client = redis.

What is Sinon stub ()?

The sinon. stub() substitutes the real function and returns a stub object that you can configure using methods like callsFake() . Stubs also have a callCount property that tells you how many times the stub was called. For example, the below code stubs out axios.

What is Redis Javascript?

Redis, an in-memory database that stores data in the server memory, is a popular tool to cache data. You can connect to Redis in Node. js using the node-redis module, which gives you methods to retrieve and store data in Redis.

How does Sinon JS work?

Sinon replaces the whole request module (or part of it) during the test execution, making the stub available via require('request') and then restore it after the tests are finished? require('request') will return the same (object) reference, that was created inside the "request" module, every time it's called.


2 Answers

What you could do is use something like Proxyquire or Rewire. I'll be using rewire for the example.

Your snippet of code you want to stub:

var redisClient = redis.createClient(redisPort, redisHost);
var someValue = redisClient.get("someKey");
return someValue;

Then in your test you can use rewire:

var Rewire = require('rewire');

var myModule = Rewire("../your/module/to/test.js");

var redisMock = {
    get: sinon.spy(function(something){
             return "someValue";
         });
};

myModule.__set__('redisClient', redisMock);

This way you can have your redisClient replaced and you can check with the spy if the function was called.

like image 142
Osukaa Avatar answered Oct 24 '22 21:10

Osukaa


Few key points are:

  • Stub redisClient before loading main module.
  • Stub the CRUD methods for redisClient.

Below is my main module:

/* Main module */
const redis = require('redis');
const redisClient = redis.createClient();

function value(){
  return redisClient.get('someKey');
}

module.exports = {value: value}

Below is my test script:

/* Test */
var sinon = require('sinon');
var redis = require('redis');

// stub redis.createClient

var redisClient = {
    'get': () => "someValue"
}

var redisGetSpy = sinon.spy(redisClient, "get");
var redisClientStub = sinon.stub(redis,
                                 "createClient").callsFake(() => redisClient);

// require main module
var main = require('./main.js');

console.log(main.value(),
            redisClientStub.called,
            redisGetSpy.called, 
            redisGetSpy.callCount);
like image 28
Tushar Gautam Avatar answered Oct 24 '22 20:10

Tushar Gautam