我在node.js工作。我的应用程序通过node_redis
模块与Redis交互。我使用mocha和sinon自动测试我的应用程序。我的应用程序看起来像这样:
...snip
var redisClient = redis.createClient(redisPort, redisHost);
var someValue = redisClient.get("someKey");
return someValue;
....
我想将调用存根到redisClient.get()。要做到这一点,我还需要将调用存根到redis.createClient() - 我认为......这是我的测试代码:
...
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");
...
测试失败,AssertionError: false == "someValue"
如何删除redisClient
,或者这甚至可能?
答案 0 :(得分:8)
您可以使用Proxyquire或Rewire之类的内容。我将使用重新连线作为例子。
您想要存根的代码片段:
var redisClient = redis.createClient(redisPort, redisHost);
var someValue = redisClient.get("someKey");
return someValue;
然后在你的测试中你可以使用重新连接:
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);
通过这种方式,您可以更换redisClient,如果调用该函数,您可以检查间谍。
答案 1 :(得分:0)
您还可以使用类似redis-mock的名称,它代替了运行在内存中的node_redis
。
使用rewire
(或Jest模块模拟或任何其他方式)将模拟客户端(而不是真实客户端)加载到测试中,并针对内存版本运行所有测试。
答案 2 :(得分:0)
另一种方法是在您的类静态函数getRedis
中进行模拟。例如:
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;
您的类内部连接函数如下:
this.connection = YourClass.getRedis().createClient(port, host, optional);
答案 3 :(得分:0)
几个关键点是:
下面是我的主要模块:
/* Main module */
const redis = require('redis');
const redisClient = redis.createClient();
function value(){
return redisClient.get('someKey');
}
module.exports = {value: value}
下面是我的测试脚本:
/* 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);
答案 4 :(得分:0)
const sinon = require('sinon');
const redis = require('redis');
const { mapValues, isObject, isUndefined, noop, isFunction } = require('lodash');
let redisStub;
let redisStore = {};
const removeKeyWhenExpired = (db, key, expirationSec) => {
setTimeout(() => {
redisStore[db || 0][key] = undefined;
}, expirationSec * 1000);
};
sinon.stub(redis, 'createClient').callsFake(() => ({
on: () => { },
select: (db) => {
this.db = db;
redisStore[db] = {};
},
get: (key, callback) => callback(null, redisStore[this.db || 0][key]),
set: (key, value, ...args) => {
redisStore[this.db || 0][key] = isObject(value) ? JSON.stringify(value) : value;
if (args[0] === 'EX') {
removeKeyWhenExpired(this.db, key, args[1]);
}
const callback = args[args.length - 1] || noop;
if (isFunction(callback)) {
callback(null, true);
}
},
del: (key, callback = noop) => {
if (!isUndefined(redisStore[this.db || 0][key])) {
redisStore[this.db || 0][key] = undefined;
return callback(null, 1);
}
return callback(null, 0);
},
expireat: (key, exp, callback = noop) => {
removeKeyWhenExpired(this.db, key, exp - (new Date().getTime() / 1000));
return callback(null);
},
}));
答案 5 :(得分:-1)
起初,这对我来说似乎是微不足道的,但是我面临许多警告,特别是因为我使用jest进行测试,但不支持proxyquire。我的目标是模拟redis的请求依赖关系,所以这是我的实现方式:
// The objective is to mock this dependency
const redis = require('redis');
const redisClient = redis.createClient();
redis.set('key','value');
用rewiremock模拟依赖项:
const rewiremock = require('rewiremock/node');
const app = rewiremock.proxy('./app', {
redis: {
createClient() {
console.log('mocking createClient');
},
set() {
console.log('mocking set');
}
},
});
要注意的是,您不能使用rewire或将proxyquire
与jest
一起使用,需要像rewiremock
这样的库来模拟这种依赖关系。