单元测试连接数据库的异步函数

时间:2016-01-31 01:24:31

标签: javascript node.js unit-testing testing redis

我有一些连接到数据库(redis)并返回一些数据的函数,这些函数通常基于promises但是是异步的并且包含流。我查看并阅读了一些关于测试的内容,我选择使用tape,sinon和proxyquire,如果我嘲笑这个函数我怎么知道它有效呢?

以下函数(listKeys)在完成扫描后返回(通过promise)redis db中存在的所有键。

let methods = {
    client: client,
    // Cache for listKeys
    cacheKeys: [],
    // Increment and return through promise all keys
    // store to cacheKeys;
    listKeys: blob => {
        return new Promise((resolve, reject) => {
            blob = blob ? blob : '*';

            let stream = methods.client.scanStream({
                match: blob,
                count: 10,
            })

            stream.on('data', keys => {
                for (var i = 0; i < keys.length; i++) {
                    if (methods.cacheKeys.indexOf(keys[i]) === -1) {
                        methods.cacheKeys.push(keys[i])
                    }
                }
            })

            stream.on('end', () => {
                resolve(methods.cacheKeys)
            })

            stream.on('error', reject)
        })
    }
}

那么你如何测试这样的函数呢?

2 个答案:

答案 0 :(得分:2)

我认为有几种方法可以通过测试来执行此功能,并且所有方法都围绕配置测试使用的测试流。

我喜欢编写我认为最重要的测试用例,然后找出实现它们的方法。对我来说最重要的是像

it('should resolve cacheKeys on end')

然后需要创建一个流来提供您的功能

var Stream = require('stream');
var stream = new Stream();

然后扫描流需要由您的测试控制

您可以通过创建假客户端来实现此目的

client = {
  scanStream: (config) => { return stream }
}

然后可以使用断言配置测试

var testKeys = ['t'];

Method.listKeys().then((cacheKeys) => { 

  assert(cacheKeys).toEqual(testKeys);
  done() 
})

现在你的承诺正在等待你的流声明 将数据发送到流。

stream.emit('data', testKeys)

答案 1 :(得分:1)

一种简单的方法,通过模拟数据库流,在其上发送数据并检查是否正确保存,来测试密钥是否正确保存到cacheKeys。 E.g:

// Create a mock stream to substitute database
var mockStream = new require('stream').Readable();

// Create a mock client.scanStream that returns the mocked stream
var client = {
    scanStream: function () {
        return mockStream;
    }
};

// Assign the mocks to methods
methods.client = client;

// Call listKeys(), so the streams get prepared and the promise awaits resolution
methods.listKeys()
    .then(function (r) {
        // Setup asserts for correct results here
        console.log('Promise resolved with: ', r);
    });

// Send test data over the mocked stream
mockStream.emit('data', 'hello');

// End the stream to resolve the promise and execute the asserts
mockStream.emit('end');