javascript - 如何测试 fs.read 函数回调
问题描述
我想测试以下代码。
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
函数,因为lastLines
调用后该字段尚未填充setupFile
。我正在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/stackoverflow/66332328
推荐阅读
- php - 如何在 Laravel 5.7 的登录会话期间使用 Auth() 注册
- python - 在一个简单的 python 脚本中创建一个 django 密码
- ruby-on-rails - 使用 ckeditor 上传文件时显示未定义的消息
- x11 - 有没有办法使用 X11/Xt 从父窗口返回所有小部件?
- java - 没有 volatile 的延迟初始化/记忆
- java - JAX-RS 在 RESTEasy 中接收 JSON 时自动解组自定义对象
- php - 如何通过 HTTPS 读取和验证我的 PHP 服务器上是否有图像?
- docker - 无法使用新图像在 docker compose 中启动容器
- css - 如何推动每个
- 元素垂直换行
- java - 如何在链接列表中按属性删除对象?