简体   繁体   English

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

[英]Unit testing asynchronous function which connects to database

Well I have some functions which connect to database (redis) and return some data, those functions usually are based on promises but are asynchronous and contain streams. 我有一些连接到数据库(redis)并返回一些数据的函数,这些函数通常基于promises但是是异步的并且包含流。 I looked and read some things about testing and I chose to go with tape , sinon and proxyquire, if I mock this function how I would know that it works? 我查看并阅读了一些关于测试的内容,我选择使用磁带 ,sinon和proxyquire,如果我嘲笑这个函数我怎么知道它有效?

The following function (listKeys) returns (through promise) all the keys that exist in the redis db after completes the scanning. 以下函数(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)
        })
    }
}

So how do you test a function like that? 那么你如何测试这样的功能呢?

I think there are a couple ways To excercise this function through a test and all revolve around configuring a test stream to be used by your test. 我认为有几种方法可以通过测试来执行此功能,并且所有方法都围绕配置测试使用的测试流。

I like to write test cases that I think are important first , then figure out a way to implement them. 我喜欢编写我认为最重要的测试用例,然后找出实现它们的方法。 To me the most important is something like 对我来说最重要的是像

it('should resolve cacheKeys on end')

Then a stream needs to be created to provide to your function 然后需要创建一个流来提供您的功能

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

Then scan stream needs to be controlled by your test 然后扫描流需要由您的测试控制

You could do this by creating a fake client 你可以通过创建一个假客户端来做到这一点

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

Then a test can be configured with your assertion 然后可以使用您的断言配置测试

var testKeys = ['t'];

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

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

Now that your promise is waiting on your stream with an assertion Send data to stream. 现在您的承诺正在等待您的流,并使用断言将数据发送到流。

stream.emit('data', testKeys)

A simple way to test whether the keys get saved to cacheKeys properly by mocking the DB stream, sending data over it and checking whether it got saved properly. 一种简单的方法,通过模拟数据库流,在其上发送数据并检查是否正确保存,来测试密钥是否正确保存到cacheKeys。 Eg: 例如:

// 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');

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM