2015-09-30 5 views
1

Я пытался запустить этот тест в течение 2 дней подряд и теперь я не могу понять, что случилось с ним:Mocha проверяет время при использовании обещаний и пропускает код, почему?

/*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) как тест асинхронного бы

Любых идей?

+0

две проблемы, которые я вижу: функция «tarPromise» возвращает неопределенные, а не обещания, а 'verifyDir' не вызывается в цепочке, просто передается. Кроме того, добавление блока catch в цепочку обещаний может помочь выявить проблему ... – mido

+0

Плохо, я сделал опечатки, когда отформатировал код для SO. Я отредактировал вопрос, чтобы исправить ошибки. Я также добавил блок catch, но он никогда ничего не печатает, когда я запускаю код. – springloaded

+1

проворно [этот вопрос] (https://github.com/petkaantonov/bluebird/issues/225)? – mido

ответ

2

Ваша проблема в том, что fs.createReadStream является синхронным и возвращает ReadableStream, который считывает данные в память кусками. PromisifyAll преобразует обратные вызовы в асинхронные функции в обещания, а не синхронные функции в асинхронные.

Возможно, что вы хотите использовать 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); 
    }); 
}); 

У меня есть утверждение установить на неисправного утверждение, чтобы продемонстрировать, что это на самом деле поражает обещание цепи.

+0

Спасибо, на основании вашего ответа, я закончил перемещение fs.createReadStream в tarPromise, и это решило проблему. Я ожидал, что createReadStreamAsync передаст поток на следующий, затем(), но это было не так. Ваше решение работает, если вы используете буферы, я хотел придерживаться потоков, потому что мой tar.extract работает с потоками. – springloaded

+0

Если вы снова столкнулись с этой проблемой, вы можете обернуть буфер потоком. см. http://stackoverflow.com/a/16044400/151445. Это не позволяет избежать чтения всего файла в буфер памяти, но он украшает буферы, которые будут использоваться вашим tar.extract. Если ваша библиотека является общедоступной, может быть даже приятно разоблачить ее для пользователей. –

Смежные вопросы