Stubbing Redis interactions in javascript using Sinon

岁酱吖の 提交于 2019-12-18 03:33:09

问题


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?


回答1:


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.




回答2:


You can also use something like redis-mock which is a drop in replacement for node_redis that runs in memory.

Use rewire (or Jest module mocks or whatever) to load the mock client in your tests instead of the real client and run all your tests against the in-memory version.




回答3:


The other way is to do in your class static function getRedis and mock it. For example:

let redis = {
   createClient: function() {},
};
let connection = {
   saddAsync: function() {},
   spopAsync: function() {},
};
let saddStub = sinon.stub(connection, 'saddAsync');
sinon.stub(redis, 'createClient').returns(connection);
sinon.stub(Redis, 'getRedis').returns(redis);

expect(saddStub).to.be.calledOnce;

Inside your class connect function looks like:

this.connection = YourClass.getRedis().createClient(port, host, optional);



回答4:


This initially seemed very trivial to me, but I was faced with a lot of caveats, particularly because I was using jest for testing, which does not supports proxyquire. My objective was to mock the request dependency of redis, so here's how I achieved it:

// The objective is to mock this dependency
const redis = require('redis');

const redisClient = redis.createClient();
redis.set('key','value');

Mocking dependency with rewiremock:

const rewiremock = require('rewiremock/node');

const app = rewiremock.proxy('./app', {
  redis: {
    createClient() { 
      console.log('mocking createClient');
    },
    set() {
      console.log('mocking set');
    }
  },
});

The catch is that you can't use rewire, or proxyquire with jest, that you need a library like rewiremock to mock this dependency.

REPL example



来源:https://stackoverflow.com/questions/24937212/stubbing-redis-interactions-in-javascript-using-sinon

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!