在整个摩卡testing之前运行asynchronous代码

我正在寻找一种方法来在整个摩卡testing之前运行asynchronous代码。

下面是一个testing的例子,它使用了一系列参数和期望值,并循环了这个数组中的所有项来产生函数断言。

var assert = require('assert') /* global describe, it*/ var fn = function (value) { return value + ' ' + 'pancake' } var tests = [ { 'arg': 'kitty', 'expect': 'kitty pancake' }, { 'arg': 'doggy', 'expect': 'doggy pancake' }, ] describe('example', function () { tests.forEach(function (test) { it('should return ' + test.expect, function (){ var value = fn(test.arg) assert.equal(value, test.expect) }) }) }) 

现在,我的问题是,如果testing的价值来自一个承诺,这将如何工作:

 var assert = require('assert') var Promise = require('bluebird') /* global describe, it*/ var fn = function (value) { return value + ' ' + 'pancake' } function getTests () { return Promise.resolve('kitty pancake') .delay(500) .then(function (value) { return [ { 'arg': 'kitty', 'expect': value }, { 'arg': 'doggy', 'expect': 'doggy pancake' } ] }) } getTests().then(function (tests) { describe('example', function () { tests.forEach(function (test) { it('should return ' + test.expect, function (){ var value = fn(test.arg) assert.equal(value, test.expect) }) }) }) }) 

也试过了:

 describe('example', function () { getTests().then(function (tests) { tests.forEach(function (test) { it('should return ' + test.expect, function (){ var value = fn(test.arg) assert.equal(value, test.expect) }) }) }) }) 

然而,在这个例子中,没有一个testing运行,因为摩卡不承认描述语句,因为它在承诺之内。

before / beforeEach将不会做任何事情来帮助进行格式testing,除非这是一个beforeTest钩子,它会为mocha提供在整个testing之前需要运行的asynchronous操作的知识。

我不知道是否有任何简单的方法来做到这一点,但你可以尝试以编程方式运行摩卡 。

这可能是一个有点肮脏的版本,只是为了展示这个想法。

data.js

 var Promise = require('bluebird') module.exports.tests = [] function getTests () { return Promise.resolve('kitty pancake') .delay(500) .then(function (value) { module.exports.tests = [ { 'arg': 'kitty', 'expect': value }, { 'arg': 'doggy', 'expect': 'doggy pancake' } ] }) } module.exports.getTests = getTests 

test-launcher.js

 var Mocha = require('mocha'), fs = require('fs'), path = require('path') // First, you need to instantiate a Mocha instance. var mocha = new Mocha() // Then, you need to use the method "addFile" on the mocha // object for each file. // Here is an example: fs.readdirSync('test').filter(function(file){ // Only keep the .js files return file.substr(-3) === '.js' }).forEach(function(file){ // Use the method "addFile" to add the file to mocha mocha.addFile( path.join('test', file) ) }) // make sure your tests are loaded before running the tests require('./data').getTests().then(function () { // Now, you can run the tests. mocha.run(function(failures){ process.on('exit', function () { process.exit(failures) }) }) }) 

test/index.js

 var assert = require('assert') var tests = require('../data').tests var fn = function (value) { return value + ' ' + 'pancake' } describe('test', function () { describe('example', function () { tests.forEach(function (test) { it('should return ' + test.expect, function (){ var value = fn(test.arg) assert.equal(value, test.expect) }) }) }) }) 

然后你可以通过运行test-launcher.js运行你的rest。

我将使用async / await和延迟选项如下:

 setTimeout(async () => { //get tests async const tests = await getTests() describe('example', async () => { tests.forEach((test) => { it(`test name: ${test.name} `, () => { console.log(test.name) }) }) }) run() }, 1000) 

作为Daniel Perez方法的替代方法,您还可以使用命令行开关--delay并在第一次run()调用时启动testing 。 通过asynchronous地延迟run() ,可以事先asynchronous地注册describe和s。 但是请注意,只能调用run()一次,即只能在一个testing文件中调用。 因此,我在./test/创build了一个asynchronoustesting./test/并在./test/创build了每个asynchronoustesting:

 // ./test/asyncRunner.js "use strict"; const allAsyncPaths = [ "test-featureA", "test-featureB", ].map(a => "../testAsync/" + a); const allAsyncTestFunctions = allAsyncPaths.map(require); Promise.resolve({ }).then(function() { const allPromises = allAsyncTestFunctions.map(a => a()); return Promise.all(allPromises); }).then(function() { run(); // mocha waits for run() because of --delay flag }).catch(function(err) { console.error(err); }); 

 // ./testAsync/test-featureA.js "use strict"; function asyncTestRegistrator() { return Promise.resolve({ }).then(function() { return getTestsAsync(); }).then(function(tests) { describe('example', function () { tests.forEach(function (test) { it('should return ' + test.expect, function (){ var value = fn(test.arg); assert.equal(value, test.expect); }); }); }); } module.exports = asyncTestRegistrator; 

我会在it调用中移动asynchronous逻辑。 对unit testing过于乐观是一种代码异味,当他们不仅需要debugging和修复失败的testing,而且还必须debugging和修复那些甚至没有定义和运行的testing时,他们可能只会激怒其他开发人员,因为奇怪的设置代码有错误。 尽量不要去那里。

 var assert = require('assert') var Promise = require('bluebird') /* global describe, it*/ var fn = function(value) { return value + ' ' + 'pancake' } function getTests() { return Promise.resolve('kitty pancake') .delay(500) .then(function(value) { return [ { 'arg': 'kitty', 'expect': value }, { 'arg': 'doggy', 'expect': 'doggy pancake' } ] }) } describe('example', function() { it('should handle many things', function(done) { getTests().then(function(tests) { tests.forEach(function(test) { var value = fn(test.arg) assert.equal(value, test.expect, 'should return ' + test.expect) }) done() }) }) })