ストリームを大量に処理するnode-jsモジュールの1つをユニットテストしようとしています。モジュール内にトリガーしたい「.on( 'data/end)」リスナーがあるため、ストリーム(書き込み先)をモックしようとしています。基本的に、私は次のようなことができるようにしたいと思っています。
var mockedStream = new require('stream').readable();
mockedStream.on('data', function withData('data') {
console.dir(data);
});
mockedStream.on('end', function() {
console.dir('goodbye');
});
mockedStream.Push('hello world');
mockedStream.close();
これは実行されますが、プッシュを実行した後、「on」イベントが発生することはありません(.close()は無効です)。
ストリームで見つけることができるすべてのガイダンスでは、新しいストリームを作成するための基礎として「fs」または「net」ライブラリを使用しています( https://github.com/substack/stream-handbook )、または彼らはそれをシノンでモックアウトしますが、モックは非常に長く非常に速くなります。
このようなダミーストリームを提供する良い方法はありますか?
プッシュを使用する代わりに、「。emit(<event>、<data>);」を使用する必要がありました。
私のモックコードは機能し、次のようになります。
var mockedStream = new require('stream').Readable();
mockedStream._read = function(size) { /* do nothing */ };
myModule.functionIWantToTest(mockedStream); // has .on() listeners in it
mockedStream.emit('data', 'Hello data!');
mockedStream.emit('end');
受け入れの答えは部分的にしか正しくありません。発生するイベントだけが必要な場合は、.emit('data', datum)
を使用しても問題ありませんが、このモックストリームを他の場所にパイプする必要がある場合は、機能しません。
読み取り可能なストリームのモックは驚くほど簡単で、読み取り可能なライブラリのみが必要です。
let eventCount = 0;
const mockEventStream = new Readable({
objectMode: true,
read: function (size) {
if (eventCount < 10) {
eventCount = eventCount + 1;
return this.Push({message: `event${eventCount}`})
} else {
return this.Push(null);
}
}
});
これで、このストリームをどこにでもパイプでき、「data」と「end」が起動します。
ノードドキュメントからの別の例: https://nodejs.org/api/stream.html#stream_an_example_counting_stream
@flacnutの回答に基づいて、(NodeJS 12以降で)Readable.from()
を使用してこれを行い、データ(ファイル名のリスト)がプリロードされたストリームを構築しました。
const mockStream = require('stream').Readable.from([
'file1.txt',
'file2.txt',
'file3.txt',
])
私の場合、fast-glob.streamによって返されるファイル名のストリームをモックしたかったのです。
const glob = require('fast-glob')
// inject the mock stream into glob module
glob.stream = jest.fn().mockReturnValue(mockStream)
テストされている関数では:
const stream = glob.stream(globFilespec)
for await (const filename of stream) {
// filename = file1.txt, then file2.txt, then file3.txt
}
チャームのように機能します!
もっと簡単な方法があります:stream.PassThrough
Nodeのstream.PassThrough
クラスを見逃しやすいことがわかりました。これは、あなたが探しているものだと思います。
From Node docs:
Stream.PassThroughクラスは、入力バイトを出力に渡すだけのTransformストリームの簡単な実装です。 その目的は主に例とテストのためです...
質問のコードを変更:
const { PassThrough } = require('stream');
const mockedStream = new PassThrough(); // <----
mockedStream.on('data', (d) => {
console.dir(d);
});
mockedStream.on('end', function() {
console.dir('goodbye');
});
mockedStream.emit('data', 'hello world');
mockedStream.end(); // <-- end. not close.
mockedStream.destroy();
mockedStream.Push()
も機能しますが、Buffer
として機能するため、次のようにします。console.dir(d.toString());