如何使用 sinon.useFakeTimers 在 javascript 单元测试中设置超时
How to set timeout in a javascript unit test using sinon.useFakeTimers
我正在尝试测试以下方法:
endSocketConn(socket) {
if(!socket) {
return;
}
socket.setTimeout(5000, () => {
socket.destroy();
});
socket.end('commandToSend');
}
我需要测试的场景是,如果超过 5 秒,则必须调用 socket.destroy() 一次
describe('Testing API | socketPool methods', async function () {
beforeEach(async function () {
let clock = sinon.useFakeTimers();
let socketMock = {
setTimeout: sinon.spy(),
destroy: sinon.spy(),
end: sinon.spy(),
};
});
afterEach(async function () {
clock && clock.restore();
});
describe('Testing endSocketConn() function', function () {
it('It should execute socket.destroy if timeout occurred after sending commandToSend', async function () {
let result;
let error = false;
try {
clock.tick(6000);
result = await file.endSocketConn(socketMock);
} catch (err) {
error = err;
}
expect(error).to.be.false;
sinon.assert.callCount(socketMock.setTimeout, 1);
sinon.assert.callCount(socketMock.end, 1);
sinon.assert.callCount(socketMock.destroy, 1);
// AssertError: expected spy to be called once but was called 0 times
});
});
知道为什么没有正确模拟超时吗?
不需要使用sinon.useFakeTimers()
,因为我们可以使用存根实现一个与真正无关的方法setTimeout
.
例如
file.js
:
endSocketConn(socket) {
if (!socket) {
return;
}
socket.setTimeout(5000, () => {
socket.destroy();
});
socket.end('commandToSend');
},
};
export { file };
file.test.js
:
import sinon from 'sinon';
import { file } from './file';
describe('Testing API | EslSocketPoolHandler methods', function () {
let socketMock;
beforeEach(function () {
socketMock = {
setTimeout: sinon.stub(),
destroy: sinon.spy(),
end: sinon.spy(),
};
});
describe('Testing endSocketConn() function', function () {
it('It should execute socket.destroy if timeout occurred after sending commandToSend', function () {
socketMock.setTimeout.callsFake((ms, cb) => {
cb();
});
file.endSocketConn(socketMock);
sinon.assert.callCount(socketMock.setTimeout, 1);
sinon.assert.callCount(socketMock.end, 1);
sinon.assert.callCount(socketMock.destroy, 1);
});
});
});
单元测试结果:
Testing API | EslSocketPoolHandler methods
Testing endSocketConn() function
✓ It should execute socket.destroy if timeout occurred after sending commandToSend
1 passing (7ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 85.71 | 50 | 100 | 85.71 |
file.ts | 85.71 | 50 | 100 | 85.71 | 4
----------|---------|----------|---------|---------|-------------------
我正在尝试测试以下方法:
endSocketConn(socket) {
if(!socket) {
return;
}
socket.setTimeout(5000, () => {
socket.destroy();
});
socket.end('commandToSend');
}
我需要测试的场景是,如果超过 5 秒,则必须调用 socket.destroy() 一次
describe('Testing API | socketPool methods', async function () {
beforeEach(async function () {
let clock = sinon.useFakeTimers();
let socketMock = {
setTimeout: sinon.spy(),
destroy: sinon.spy(),
end: sinon.spy(),
};
});
afterEach(async function () {
clock && clock.restore();
});
describe('Testing endSocketConn() function', function () {
it('It should execute socket.destroy if timeout occurred after sending commandToSend', async function () {
let result;
let error = false;
try {
clock.tick(6000);
result = await file.endSocketConn(socketMock);
} catch (err) {
error = err;
}
expect(error).to.be.false;
sinon.assert.callCount(socketMock.setTimeout, 1);
sinon.assert.callCount(socketMock.end, 1);
sinon.assert.callCount(socketMock.destroy, 1);
// AssertError: expected spy to be called once but was called 0 times
});
});
知道为什么没有正确模拟超时吗?
不需要使用sinon.useFakeTimers()
,因为我们可以使用存根实现一个与真正无关的方法setTimeout
.
例如
file.js
:
endSocketConn(socket) {
if (!socket) {
return;
}
socket.setTimeout(5000, () => {
socket.destroy();
});
socket.end('commandToSend');
},
};
export { file };
file.test.js
:
import sinon from 'sinon';
import { file } from './file';
describe('Testing API | EslSocketPoolHandler methods', function () {
let socketMock;
beforeEach(function () {
socketMock = {
setTimeout: sinon.stub(),
destroy: sinon.spy(),
end: sinon.spy(),
};
});
describe('Testing endSocketConn() function', function () {
it('It should execute socket.destroy if timeout occurred after sending commandToSend', function () {
socketMock.setTimeout.callsFake((ms, cb) => {
cb();
});
file.endSocketConn(socketMock);
sinon.assert.callCount(socketMock.setTimeout, 1);
sinon.assert.callCount(socketMock.end, 1);
sinon.assert.callCount(socketMock.destroy, 1);
});
});
});
单元测试结果:
Testing API | EslSocketPoolHandler methods
Testing endSocketConn() function
✓ It should execute socket.destroy if timeout occurred after sending commandToSend
1 passing (7ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 85.71 | 50 | 100 | 85.71 |
file.ts | 85.71 | 50 | 100 | 85.71 | 4
----------|---------|----------|---------|---------|-------------------