Stubbing взаимодействия Redis в javascript с использованием Sinon
Я работаю в node.js. Мое приложение взаимодействует с Redis через модуль node_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
, или это возможно?
Ответы
Ответ 1
Что вы можете сделать, это использовать что-то вроде Proxyquire или Rewire. Я буду использовать rewire для примера.
Ваш фрагмент кода, который вы хотите заглушить:
var redisClient = redis.createClient(redisPort, redisHost);
var someValue = redisClient.get("someKey");
return someValue;
Затем в вашем тесте вы можете использовать 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);
Таким образом, вы можете заменить свой redisClient, и вы можете проверить со шпионом, если функция была вызвана.
Ответ 2
Вы также можете использовать что-то вроде redis-mock, который заменяет node_redis
который работает в памяти.
Используйте rewire
(или Jest-модуль Jest или что-то еще), чтобы загрузить фиктивный клиент в ваши тесты вместо реального клиента и запустить все ваши тесты для версии в памяти.
Ответ 3
Другой способ - сделать в вашем классе статическую функцию 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);
Ответ 4
Изначально это показалось мне тривиальным, но я столкнулся с множеством предостережений, особенно потому, что для тестирования я использовал 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
, чтобы высмеивать эту зависимость.
Пример REPL