如何测试 fs.read 函数回调
How to test the fs.read function callback
我想测试下面的代码。
class Tailer {
constructor(logFilePath) {
this.logFilePath = logFilePath;
this.seekFrom = 0;
this.lastLines = [];
}
setupFile(newlinepointer) {
var bytesToRead = this.fileSizeInBytes - newlinepointer
fs.open(this.logFilePath, 'r', (errOpen, fd) => {
fs.read(fd, Buffer.alloc(bytesToRead), 0, bytesToRead, newlinepointer, (errRead, bytesRead, buffer) => {
var data = buffer.toString('utf8')
this.lastLines = data.split('\n')
});
});
}
}
我的测试代码是
describe("tailer", function() {
describe("setupFile", function() {
it("should fill last 10 lines from given pointer", function() {
let tailer = new Tailer('test/test.log', (data) => {})
tailer.setupFile(5)
assert.equal(tailer.lastLines.length, 10);
});
});
});
由于 fs.read
正在使用回调,我无法测试 setupFile
函数,因为调用 setupFile
后 lastLines
字段尚未填充。我正在使用 mocha
进行测试。
您应该使用 sinonjs 存根库来存根 fs.open()
和 fs.read()
方法。为他们提供伪造的实现。然后你可以在你的测试用例中手动执行回调。
例如
index.js
:
import fs from 'fs';
export class Tailer {
logFilePath;
seekFrom;
lastLines;
fileSizeInBytes;
constructor(logFilePath) {
this.logFilePath = logFilePath;
this.seekFrom = 0;
this.lastLines = [];
this.fileSizeInBytes = 100;
}
setupFile(newlinepointer) {
var bytesToRead = this.fileSizeInBytes - newlinepointer;
fs.open(this.logFilePath, 'r', (errOpen, fd) => {
fs.read(fd, Buffer.alloc(bytesToRead), 0, bytesToRead, newlinepointer, (errRead, bytesRead, buffer) => {
var data = buffer.toString('utf8');
this.lastLines = data.split('\n');
});
});
}
}
index.test.js
:
import { Tailer } from './';
import fs from 'fs';
import sinon from 'sinon';
import { expect } from 'chai';
describe('66332328', () => {
it('should pass', () => {
const openStub = sinon.stub(fs, 'open').callsFake((filepath, flags, callback) => {
callback(null, 1);
});
const readStub = sinon.stub(fs, 'read').callsFake((fd, buffer, offset, length, position, callback) => {
callback && callback(null, 100, Buffer.from('teresa teng\nbest singer'));
});
const tailer = new Tailer('./test.text');
tailer.setupFile(50);
expect(tailer.lastLines).to.be.deep.equal(['teresa teng', 'best singer']);
sinon.assert.calledWithExactly(openStub, './test.text', 'r', sinon.match.func);
sinon.assert.calledWithExactly(readStub, 1, Buffer.alloc(50), 0, 50, 50, sinon.match.func);
});
});
单元测试结果:
66332328
✓ should pass
1 passing (6ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.ts | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
源代码:https://github.com/mrdulin/expressjs-research/tree/master/src/Whosebug/66332328
我想测试下面的代码。
class Tailer {
constructor(logFilePath) {
this.logFilePath = logFilePath;
this.seekFrom = 0;
this.lastLines = [];
}
setupFile(newlinepointer) {
var bytesToRead = this.fileSizeInBytes - newlinepointer
fs.open(this.logFilePath, 'r', (errOpen, fd) => {
fs.read(fd, Buffer.alloc(bytesToRead), 0, bytesToRead, newlinepointer, (errRead, bytesRead, buffer) => {
var data = buffer.toString('utf8')
this.lastLines = data.split('\n')
});
});
}
}
我的测试代码是
describe("tailer", function() {
describe("setupFile", function() {
it("should fill last 10 lines from given pointer", function() {
let tailer = new Tailer('test/test.log', (data) => {})
tailer.setupFile(5)
assert.equal(tailer.lastLines.length, 10);
});
});
});
由于 fs.read
正在使用回调,我无法测试 setupFile
函数,因为调用 setupFile
后 lastLines
字段尚未填充。我正在使用 mocha
进行测试。
您应该使用 sinonjs 存根库来存根 fs.open()
和 fs.read()
方法。为他们提供伪造的实现。然后你可以在你的测试用例中手动执行回调。
例如
index.js
:
import fs from 'fs';
export class Tailer {
logFilePath;
seekFrom;
lastLines;
fileSizeInBytes;
constructor(logFilePath) {
this.logFilePath = logFilePath;
this.seekFrom = 0;
this.lastLines = [];
this.fileSizeInBytes = 100;
}
setupFile(newlinepointer) {
var bytesToRead = this.fileSizeInBytes - newlinepointer;
fs.open(this.logFilePath, 'r', (errOpen, fd) => {
fs.read(fd, Buffer.alloc(bytesToRead), 0, bytesToRead, newlinepointer, (errRead, bytesRead, buffer) => {
var data = buffer.toString('utf8');
this.lastLines = data.split('\n');
});
});
}
}
index.test.js
:
import { Tailer } from './';
import fs from 'fs';
import sinon from 'sinon';
import { expect } from 'chai';
describe('66332328', () => {
it('should pass', () => {
const openStub = sinon.stub(fs, 'open').callsFake((filepath, flags, callback) => {
callback(null, 1);
});
const readStub = sinon.stub(fs, 'read').callsFake((fd, buffer, offset, length, position, callback) => {
callback && callback(null, 100, Buffer.from('teresa teng\nbest singer'));
});
const tailer = new Tailer('./test.text');
tailer.setupFile(50);
expect(tailer.lastLines).to.be.deep.equal(['teresa teng', 'best singer']);
sinon.assert.calledWithExactly(openStub, './test.text', 'r', sinon.match.func);
sinon.assert.calledWithExactly(readStub, 1, Buffer.alloc(50), 0, 50, 50, sinon.match.func);
});
});
单元测试结果:
66332328
✓ should pass
1 passing (6ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.ts | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
源代码:https://github.com/mrdulin/expressjs-research/tree/master/src/Whosebug/66332328