问题
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