test node framework before node.js testing stream tdd

node.js - framework - node test before



TDD/prueba con transmisiones en NodeJS (7)

Hecho streamtest para ese propósito. No solo hace que las pruebas de flujo sean más limpias, sino que también permite probar flujos de V1 y V2 https://www.npmjs.com/package/streamtest

He estado tratando de encontrar una forma razonable de probar el código que usa transmisiones. ¿Alguien ha encontrado una forma / marco razonable para ayudar a probar el código que usa flujos en nodejs?

Por ejemplo:

var fs = require(''fs''), request = require(''request''); module.exports = function (url, path, callback) { request(url) .pipe(fs.createWriteStream(path)) .on(''finish'', function () { callback(); }); };

Mi forma actual de probar este tipo de código implica tanto simplificar el código con transmisiones que puedo resumirlo en un fragmento de código no probado o escribiendo algo como esto:

var rewire = require(''rewire''), download = rewire(''../lib/download''), stream = require(''stream''), util = require(''util''); describe(''download'', function () { it(''should download a url'', function (done) { var fakeRequest, fakeFs, FakeStream; FakeStream = function () { stream.Writable.call(this); }; util.inherits(FakeStream, stream.Writable); FakeStream.prototype._write = function (data, encoding, cb) { expect(data.toString()).toEqual("hello world") cb(); }; fakeRequest = function (url) { var output = new stream.Readable(); output.push("hello world"); output.push(null); expect(url).toEqual(''http://hello''); return output; }; fakeFs = { createWriteStream: function (path) { expect(path).toEqual(''hello.txt''); return new FakeStream(); } }; download.__set__(''fs'', fakeFs); download.__set__(''request'', fakeRequest); download(''http://hello'', ''hello.txt'', function () { done(); }); }); });

¿Alguien ha encontrado formas más elegantes de probar transmisiones?


La mejor forma que he encontrado es usar eventos

const byline = require(''byline''); const fs = require(''fs''); it(''should process all lines in file'', function(done){ //arrange let lines = 0; //file with 1000 lines let reader = fs.readFileStream(''./input.txt''); let writer = fs.writeFileStream(''./output.txt''); //act reader.pipe(byline).pipe(writer); byline.on(''line'', function() { lines++; }); //assert writer.on(''close'', function() { expect(lines).to.equal(1000); done(); }); });

al pasar hecho como una devolución de llamada, mocha espera hasta que se llame antes de continuar.


Lee el flujo en la memoria y compáralo con el búfer esperado.

it(''should output a valid Stream'', (done) => { const stream = getStreamToTest(); const expectedBuffer = Buffer.from(...); let bytes = new Buffer(''''); stream.on(''data'', (chunk) => { bytes = Buffer.concat([bytes, chunk]); }); stream.on(''end'', () => { try { expect(bytes).to.deep.equal(expectedBuffer); done(); } catch (err) { done(err); } }); });



Puede probar secuencias utilizando MemoryStream y sinon mediante el uso de espías. Así es como probé algunos de mis códigos.

describe(''some spec'', function() { it(''some test'', function(done) { var outputStream = new MemoryStream(); var spyCB = sinon.spy(); outputStream.on(''data'', spyCB); doSomething(param, param2, outputStream, function() { sinon.assert.calledWith(spyCB, ''blah''); done(); }); }); });


También he estado usando memorystream , pero luego he puesto mis aserciones en el evento finish . De esta forma, se parece más a un uso real de la secuencia que se prueba:

require(''chai'').should(); var fs = require(''fs''); var path = require(''path''); var MemoryStream = require(''memorystream''); var memStream = MemoryStream.createWriteStream(); /** * This is the Transform that we want to test: */ var Parser = require(''../lib/parser''); var parser = new Parser(); describe(''Parser'', function(){ it(''something'', function(done){ fs.createReadStream(path.join(__dirname, ''something.txt'')) .pipe(parser) .pipe(memStream) .on(''finish'', function() { /** * Check that our parser has created the right output: */ memStream .toString() .should.eql(''something''); done(); }); }); });

La comprobación de los objetos se puede hacer así:

var memStream = MemoryStream.createWriteStream(null, {objectMode: true}); . . . .on(''finish'', function() { memStream .queue[0] .should.eql({ some: ''thing'' }); done(); }); . . .


Te siento dolor

No conozco ningún marco para ayudarme con las pruebas con transmisiones, pero si echas un vistazo here , donde estoy desarrollando una biblioteca de transmisión, puedes ver cómo abordo este problema.

Aquí hay una idea de lo que estoy haciendo.

var chai = require("chai") , sinon = require("sinon") , chai.use(require("sinon-chai")) , expect = chai.expect , through2 = require(''through2'') ; chai.config.showDiff = false function spy (stream) { var agent, fn ; if (spy.free.length === 0) { agent = sinon.spy(); } else { agent = spy.free.pop(); agent.reset(); } spy.used.push(agent); fn = stream._transform; stream.spy = agent; stream._transform = function(c) { agent(c); return fn.apply(this, arguments); }; stream._transform = transform; return agent; }; spy.free = []; spy.used = []; describe(''basic through2 stream'', function(){ beforeEach(function(){ this.streamA = through2() this.StreamB = through2.obj() // other kind of streams... spy(this.streamA) spy(this.StreamB) }) afterEach(function(){ spy.used.map(function(agent){ spy.free.push(spy.used.pop()) }) }) it("must call transform with the data", function(){ var ctx = this , dataA = new Buffer(''some data'') , dataB = ''some data'' ; this.streamA.pipe(through2(function(chunk, enc, next){ expect(ctx.streamA.spy).to.have.been.calledOnce.and.calledWidth(dataA) })) this.streamB.pipe(through2(function(chunk, enc, next){ expect(ctx.streamB.spy).to.have.been.calledOnce.and.calledWidth(dataB) })) this.streamA.write(dataA) this.streamB.write(dataB) }) })

Tenga en cuenta que mi función de espía ajusta el método _transform y llama a mi espía y llama a la _transform original

Además, la función afterEach es reciclar los espías, porque puedes terminar creando cientos de ellos.

El problema se pone difícil cuando quieres probar el código asíncrono. Entonces promete a tu mejor amigo. El enlace que di más arriba tiene algo de muestra.