Mocha 测试在使用 promises 时超时并跳过代码,为什么?
Mocha test times out when using promises and skips over code, why?
我已经连续 2 天尝试 运行 这个测试了,但我不知道它有什么问题:
/*eslint-env mocha */
// var expect = require('chai').expect;
var chai = require('chai');
var chaiAsPromised = require("chai-as-promised");
var expect = chai.expect;
var Promise = require('bluebird');
var Archive = require('../lib/archive');
var path = require('path');
var fs = Promise.promisifyAll(require('fs-extra'));
var globAsync = Promise.promisify(require('glob'));
var tar = require('tar-fs');
var zlib = Promise.promisifyAll(require('zlib'));
chai.use(chaiAsPromised);
describe('Archive', function() {
var pkg;
var archive_location;
var subject;
beforeEach(function() {
pkg = {
name: 'test_0790feebb1',
recipient_name: 'Test',
files: {
letter: '../documents/letters/test/letter.tex',
resume: '../documents/cover/cover.tex'
},
compiled_files: {
package: '../documents/letters/test/test.pdf'
}
};
archive_location = path.resolve('archives/test_0790feebb1.tar.gz');
subject = new Archive(pkg);
});
after(function() {
return globAsync('archives/test*')
.each(function(filename) {
return fs.removeAsync(filename);
});
});
describe('#make', function() {
it('has the correct directory structure', function() {
// debugger;
var tmp_extract_path = path.resolve('test/.tmp');
var tarPromise = function(data) {
console.log('tarP'); // never run
return new Promise(function(reject, resolve) {
data
.pipe(zlib.Unzip())
.pipe(tar.extract(tmp_extract_path))
.on('error', reject)
.on('end', resolve);
});
};
var verifyDir = function() {
console.log('verD'); // never run
return Promise.all([
'code',
'pdf',
'code/repo',
'code/documents',
'code/documents/letters',
'code/documents/letters/test',
'code/documents/letters/shared',
'code/documents/cover',
'code/documents/letters'
].map(function(subpath) {
return fs.statAsync(path.resolve(tmp_extract_path, subpath));
}));
};
return fs.createReadStreamAsync(archive_location)
.then(function(data) { return tarPromise(data); })
.then(function() { return verifyDir(); })
.then(function(files) {
console.log(files); // never run
return expect(true).to.be.true;
})
.catch(function(e) { console.log(e); });
});
});
});
各种 console.log 甚至从未执行过,最终测试超时,没有任何错误或堆栈跟踪。
我不知道我做错了什么,现在承诺伤害了我的大脑。当我使用节点检查器 运行 代码并取消注释断点时,我可以看到 this._runnable._trace
的值是 "done() called multiple times"
。我不知道这是否是一个实际错误,也不知道如果这是一个错误为什么它不抛出异常。我无法解释为什么会发生这种情况,因为我不再使用任何带有承诺的 done()
回调,并且我的测试以 function()
开始,而不是像异步测试那样 function(done)
有什么想法吗?
你的问题是 fs.createReadStream
是同步的,而 returns 是一个 ReadableStream,它以块的形式将数据读入内存。 PromisifyAll
将异步函数的回调转换为 promise,而不是同步函数为异步。
可能你想要的是使用fs.readFileAsync
:
var Promise = require('bluebird');
var fs = Promise.promisifyAll(require('fs'));
var path = require('path')
var archive_location = path.resolve('example.zip');
var assert = require('assert');
describe('This', function(){
it('should work', function(){
return fs.readFileAsync(archive_location).
then(function(data) {
assert.notEqual(data.length, data.length);
return data;
}).
catch(console.log);
});
});
我将断言设置为失败断言,以证明这实际上命中了承诺链。
我已经连续 2 天尝试 运行 这个测试了,但我不知道它有什么问题:
/*eslint-env mocha */
// var expect = require('chai').expect;
var chai = require('chai');
var chaiAsPromised = require("chai-as-promised");
var expect = chai.expect;
var Promise = require('bluebird');
var Archive = require('../lib/archive');
var path = require('path');
var fs = Promise.promisifyAll(require('fs-extra'));
var globAsync = Promise.promisify(require('glob'));
var tar = require('tar-fs');
var zlib = Promise.promisifyAll(require('zlib'));
chai.use(chaiAsPromised);
describe('Archive', function() {
var pkg;
var archive_location;
var subject;
beforeEach(function() {
pkg = {
name: 'test_0790feebb1',
recipient_name: 'Test',
files: {
letter: '../documents/letters/test/letter.tex',
resume: '../documents/cover/cover.tex'
},
compiled_files: {
package: '../documents/letters/test/test.pdf'
}
};
archive_location = path.resolve('archives/test_0790feebb1.tar.gz');
subject = new Archive(pkg);
});
after(function() {
return globAsync('archives/test*')
.each(function(filename) {
return fs.removeAsync(filename);
});
});
describe('#make', function() {
it('has the correct directory structure', function() {
// debugger;
var tmp_extract_path = path.resolve('test/.tmp');
var tarPromise = function(data) {
console.log('tarP'); // never run
return new Promise(function(reject, resolve) {
data
.pipe(zlib.Unzip())
.pipe(tar.extract(tmp_extract_path))
.on('error', reject)
.on('end', resolve);
});
};
var verifyDir = function() {
console.log('verD'); // never run
return Promise.all([
'code',
'pdf',
'code/repo',
'code/documents',
'code/documents/letters',
'code/documents/letters/test',
'code/documents/letters/shared',
'code/documents/cover',
'code/documents/letters'
].map(function(subpath) {
return fs.statAsync(path.resolve(tmp_extract_path, subpath));
}));
};
return fs.createReadStreamAsync(archive_location)
.then(function(data) { return tarPromise(data); })
.then(function() { return verifyDir(); })
.then(function(files) {
console.log(files); // never run
return expect(true).to.be.true;
})
.catch(function(e) { console.log(e); });
});
});
});
各种 console.log 甚至从未执行过,最终测试超时,没有任何错误或堆栈跟踪。
我不知道我做错了什么,现在承诺伤害了我的大脑。当我使用节点检查器 运行 代码并取消注释断点时,我可以看到 this._runnable._trace
的值是 "done() called multiple times"
。我不知道这是否是一个实际错误,也不知道如果这是一个错误为什么它不抛出异常。我无法解释为什么会发生这种情况,因为我不再使用任何带有承诺的 done()
回调,并且我的测试以 function()
开始,而不是像异步测试那样 function(done)
有什么想法吗?
你的问题是 fs.createReadStream
是同步的,而 returns 是一个 ReadableStream,它以块的形式将数据读入内存。 PromisifyAll
将异步函数的回调转换为 promise,而不是同步函数为异步。
可能你想要的是使用fs.readFileAsync
:
var Promise = require('bluebird');
var fs = Promise.promisifyAll(require('fs'));
var path = require('path')
var archive_location = path.resolve('example.zip');
var assert = require('assert');
describe('This', function(){
it('should work', function(){
return fs.readFileAsync(archive_location).
then(function(data) {
assert.notEqual(data.length, data.length);
return data;
}).
catch(console.log);
});
});
我将断言设置为失败断言,以证明这实际上命中了承诺链。