如何在JavaScript(ES6)中测试基于生成器的流控制?

时间:2014-11-10 02:53:40

标签: javascript node.js asynchronous generator

如何让Mocha等到异步函数完成?

模块

var fs = require('mz/fs');
var co = require('co');

module.exports = new filecache();

function filecache () {
  var self = this;
  var storage = storage || {};

  self.cache = co(function* (filePath, fileName) {
    if (yield fs.exists(filePath)) {
      storage[fileName] = yield fs.readFile(filePath);
    }
  });

  self.has = function has (fileName) {
    return storage.hasOwnProperty(fileName);
  };
}

测试(摩卡)

var expect = require('chai').expect;

describe('phialcash', function () {
  var filecache;
  var filePath;
  var fileName;

  beforeEach(function () {
    filecache = require('..');
    filePath = './tests/file.fixture.txt';
    fileName = filePath.split("/").pop();
  });

  describe('#exists', function () {
    it('returns true if a file exists in the cache', function () {
      filecache.cache(filePath, fileName);

      expect(filecache.has(fileName)).to.equal(true);
    });
  });
});

测试失败,因为filecache.cache(filePath, fileName);异步执行,因此在期望运行时filecache.has(fileName)仍为false。

1 个答案:

答案 0 :(得分:5)

您应该在方法调用的站点使用co,而不是在定义中。

self.cache = function* (filePath, fileName) {
    if (yield fs.exists(filePath)) {
      storage[fileName] = yield fs.readFile(filePath);
    }
};

测试时,将函数标记为异步,并将done传递给协同例程。 co将使用参数done调用done(err, response)回调。异步调用中引发的任何异常或失败的expect都会导致测试用例失败。

describe('#exists', function () {
    it('returns true if a file exists in the cache', function (done) {
      co(function * () {
        yield *filecache.cache(filePath, fileName); //generator delegation.
        expect(filecache.has(fileName)).to.equal(true);
      })(done);

    });
  });

这是使用koa的应用程序的摘录,co在内部使用yield来处理控制流。所有thunks的语句都是返回group.remove = function * (ids) { var c3Domain = this.c3Domain; let deletedCount = yield this.baseRemove(ids); if(deletedCount > 0) { let deletedGroupMappings = yield [this.connection.query(UNMAP_GROUPS, [this.c3Id, ids]), this.tag.unmapGroupTags(ids)]; let deletedQueueCount = yield this.removeQueuesFromXml(ids); if(deletedQueueCount > 0) { let eslCommands = ['reloadxml'].concat(ids.map(function (id) { return ['callcenter_config queue unload', id + '@' + c3Domain]; })); yield this.esl.multiApi(eslCommands); } } return deletedCount; }; 的异步调用。

it('should delete group', function (done) {
    co(function *() {
        let count = yield group.remove(['2000'])
        assert(count === 1)
    })(done)
})

测试用例:

{{1}}