Problem summary: 我想测试 redisCallback()
,它是在NodeJS异步回调中调用的(参见下面的代码),已使用预期的参数调用预期的次数 .
background information (skip if TL;DR):
我四处搜索但只找到了QUnit的解决方案 . 我不确定Mocha Sinon相当于这种困境的等价物 .
在我目前的测试中,Chai断言以 AssertionError: expected false to equal true
响应 .
但是,我通过在 updateRedis
函数(正在测试中)中调用 this.redisCallback
来测试它,但在 redisClient.get
异步回调之外,在这种情况下,测试套件正确检测到回调已被触发并且我的测试成功 .
这告诉我的是这是一个异步问题 . 在 redisClient.get
回调完成之后,我如何告诉Mocha / Chai等待检查断言?
Code
编写此代码是为了解决Node的问题,我需要检查Redis中的密钥是否与系统命令返回的值不同,如果更改了,请在Redis中设置新值 . 由于系统命令值将在异步调用的包含范围内(因此,不可访问/不可靠),我创建了一个函数,它返回我想要的redisClient.get回调的回调,但是将使用的密钥和系统命令值传递给用于记忆回调值的闭包 .
接近我使用HighlandJS编写的内容:
var redisClient = require('redis').createClient(config.redis.port, config.redis.host),
_ = require('highland');
// ...
redisCallback = function (resultsHash, redisKey, redisGetValue) {
var systemCmdValue = resultsHash[redisKey];
if (redisGetValue != systemCmdValue) {
redisClient.set(redisKey, systemCmdValue, function (err) { // handle errors });
}
};
// ...
updateRedis = function (err, stdout, stderr) {
// Do some stuff that's not important to this problem
var resultsHash = parseCmdResults(stdout),
redisKeys = Object.keys(resultsHash),
curriedRedisCallback = _.curry(this.redisCallback, resultsHash);
get = _.wrapCallback(redisClient.get.bind(redisClient));
redisKeys.each(function (key) {
get(key).each(curriedRedisCallback(key));
});
};
vanilla NodeJS和JavaScript中的等效实现:
var redisClient = require('redis').createClient(config.redis.port, config.redis.host);
// ...
redisCallback = function (resultsHash, redisKey, redisGetValue) {
var systemCmdValue = resultsHash[redisKey];
if (redisGetValue != systemCmdValue) {
redisClient.set(redisKey, systemCmdValue, function (err) { // handle errors });
}
};
redisCallbackWrapper = function (resultsHash) {
return function (redisKey) {
return function (redisGetValue) {
this.redisCallback(resultsHash, redisKey, redisGetValue);
};
};
};
// ...
updateRedis = function (err, stdout, stderr) {
// Do some stuff that's not important to this problem
var resultsHash = parseCmdResults(stdout),
redisKeys = Object.keys(resultsHash),
callback = redisCallbackWrapper(resultsHash),
key;
for (var i = 0; i < redisKeys; i++) {
key = redisKeys[i];
redisClient.get(key, callback(key));
}
};
我使用Mocha,Chai和Sinon的测试:
describe('when valid arguments are provided to updateRedis', function () {
var err, stdout, stderr, parsedStdout, key0, key1;
before(function () {
err = undefined;
stderr = undefined;
stdout = 'key0/value0\nkey1/value1';
key0 = 'key0';
key1 = 'key1';
parsedStdout = {};
parsedStdout[key0] = "value0";
parsedStdout[key1] = "value1";
sinon.spy(myModule, 'redisCallback');
});
after(function () {
myModule.redisCallback.restore();
});
it('calls redisCallback with the expected arguments the expected number of times', function (done) {
myModule.updateRedis(err, stdout, stderr);
// If I can get to the point where it's detected that redisCallback has been called at all,
// I can follow the documentation to figure out how to test that it's called with the expected args the expected number of times.
expect(myModule.redisCallback.called).to.equal(true);
done();
});
});