2015-11-02 3 views
2

Я пытаюсь написать тест мокки, который проходит по ошибке потока, но сбой, если поток заканчивается без ошибки.Тестирование должно проходить по ошибке потока, сбой при успешном завершении

Обнаружение ошибки не представляет проблемы, но обработчик завершения всегда вызывается, даже если поток вынужден выходить из строя. В этом коде утверждение обработчика should.exist(err) работает корректно, но затем обработчик finish все еще выдаёт ошибку.

describe('catch stream errors', function() { 
    it('should throw an error', function(done) { 
    var stream = failStream(); 

    stream.on('error', function(err) { 
     should.exist(err); 
     done(); 
    }) 

    stream.on('finish', function() { 
     done(new Error('Why does this still run?')); 
    }); 

    stream.write(); 
    stream.end(); 
    }) 
}) 

Один из способов, который кажется немного рубить, состоит в объеме errored переменная выше обработчиков, затем перевернуть его в error обработчика и проверьте значение в finish обработчика. Похоже, что должен быть лучший способ справиться с этим.

var errored = false; 

stream.on('error', function(err) { 
    should.exist(err); 
    errored = true; 
    done(); 
}) 

stream.on('finish', function() { 
    if (!errored) { 
    done(new Error('Error suppressed')); 
    } 
}); 

Полный текст here.

+1

У вас есть https://github.com/mochajs/mocha/wiki/Spies? – Sonata

+0

Спасибо за указатель. Это должно сработать, за исключением того, что мой фактический прецедент предназначен для публичного пакета, поэтому я бы предпочел не добавлять новые зависимости. – joemaller

+0

Возможно, есть ошибка в реализации данного потока? Откуда берется поток? – Ben

ответ

0

Редактировать

Я думаю, что мы оба согласны с тем, что делает эту проблему сложной является то, что многократный урон() вызовы выполняются (два события стрельбы). Если Mocha видит несколько выполненных вызовов, тест автоматически завершится с ошибкой.

Похоже, если мы сможем просто доказать, что произошло событие ошибки, наш тест будет оправдан.

Sinon - полезный libray, который предоставляет «шпионов», которые сообщают нам, когда происходят события.

Проверьте это: https://github.com/mochajs/mocha/wiki/Spies

var stream = require('stream'); 
var util = require('util'); 
var should = require('should'); 


// Writer 
util.inherits(Writer, stream.Writable); 

function Writer(opt) { 
    stream.Writable.call(this, opt); 
} 

Writer.prototype._write = function(data, encoding, callback) { 
    console.log(data.toString()); 
    // This will cause the stream to always return error 
    callback(new Error('FAIL STREAM')); 
}; 


var test = 

module.exports.run = function() { 

    describe('catch stream errors', function() { 
    it('should throw an error', function() { 
     // setup the stream that always fails 
     var stream = new Writer(); 

     // Initialize the spies 
     var errorSpy = sinon.spy(); 
     var finishSpy = sinon.spy(); 

     // When the stream events fire, 
     // callback the respective spies 
     stream.on('error', errorSpy); 
     stream.on('finish', finishSpy); 

     // Write to the stream, I setup the stream to 
     // always return an error when something is written. 

     stream.write('hello'); 
     stream.end(); 

     console.log('errorSpy Called: '+ errorSpy.called); 
     console.log('finishSpy Called: '+ finishSpy.called); 

     errorSpy.called.should.equal(true); // Mocha Test Fails If Error Event Was Not Emitted. 
     finishSpy.called.should.equal(true); // Mocha Test Fails If Finish Never Happened. 
    }); 
    }); 
}; 

Это не чистый родной решение, поскольку оно опирается на Синоне. Однако, я думаю, что это все еще хорошая альтернатива.

+1

Обработанный обработчик никогда не вызывается, если есть ошибка, так как это может произойти в случае обратного теста? Если поток * не * выдает ошибку, тест должен явным образом терпеть неудачу. – joemaller

+0

Я понимаю, что вы имеете в виду. Я просмотрю код и посмотрю, смогу ли я пересмотреть ответ. –

0

Более элегантное решение заключается в том, чтобы удалить слушателя финиша изнутри прослушивателя ошибок. Это похоже на метод cleanup в исходном файле узла lib/stream.

// Refactor out the listeners 
var onerror = function(err) { 
    should.exist(err); 
    this.removeListener('finish', onfinish); 
    done(); 
}; 

var onfinish = function() { 
    done(new Error('Expected stream to throw an error.')); 
}; 

stream.on('error', onerror); 
stream.on('finish', onfinish); 
Смежные вопросы