在对我的NodeJS应用程序进行单元测试时,我正在尝试创建一个简单的帮助器类,它将Kafka pub-sub语义转换为适合单元测试的更简单的API。
我的想法是能够像这样编写mocha unittest:
const testSubscriber = kafkaTestHelper.getTestSubscriber({topic:'test'});
return someKafkaProducer.sendAsync({topic: 'test', message: randomWord})
.then(() =>
testSubscriber.next()
).then(msg => {
msg.should.equal(randomWord);
});
当然我还会添加辅助方法,例如
testSubscriber.nextUntil(someFilter)
这是受AKKA.NET TestKit的启发,它有类似的方法。
我有两个问题:
这是一种合理的方法还是基于NodeJS中的Kafka流处理有一些更简洁的单元测试应用逻辑方法?
任何人都可以发布编码示例,说明如何让testSubscriber按照我的意图工作吗?
答案 0 :(得分:0)
这可能不是最优雅的解决方案,但它似乎有效,至少对我的初步测试而言。诀窍是创建一个不断增长的Promise列表,解析器函数通过引用保存在名为“resolvers”的数组中。然后,当有消息进入时,将使用该消息调用解析程序。通过这种方式,我可以将promises返回给任何调用next()的unittest,如果消息已经传递或者将来会传递,它将透明地工作。
我仍然觉得我在这里重新发明轮子,所以任何评论仍然会非常感激。
function TestSubscriber(consumer, initialMessageFilter) {
this.consumer = consumer;
let promiseBuffer = [];
let resolvers = [];
let resolveCounter = 0;
let isStarted = false;
const ensurePromiseBuffer = function() {
if (promiseBuffer.length === 0 || resolveCounter >= resolvers.length) {
const newPromise = new Promise(function(resolve, reject) {
resolvers.push(resolve);
});
promiseBuffer.push(newPromise);
}
}
const that = this;
this.consumer.on('message', function(message) {
if (!isStarted) {
//Determine if we should start now.
isStarted = initialMessageFilter === undefined || initialMessageFilter(message);
}
if (isStarted) {
ensurePromiseBuffer();
const resolver = resolvers[resolveCounter];
resolver(message);
resolveCounter++;
that.consumer.commit(function(err, data) {
if (err) {
//Just log any errors here as we are running inside a unittest
log.warn(err)
}
})
}
});
this.next = function() {
ensurePromiseBuffer();
return promiseBuffer.shift();
};
}
const cache = {};
module.exports = {
getTestSubscriber: function({topic}, initialMessageFilter) {
if (!cache[topic]) {
const consumer = kafka.getConsumer({topic, groupId: GROUP_ID});
cache[topic] = new TestSubscriber(consumer, initialMessageFilter);
}
return cache[topic];
}
}