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);
}
});
});
No he usado esto, y es bastante viejo, pero https://github.com/dominictarr/stream-spec podría ayudar.
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.