Я бы смоделировал / фальсифицировал все, что используется конечной точкой, и проверил, выполняется ли конечная точка в правильном порядке с правильными переменными. Во-первых, я объявил бы функцию trigger
и функцию обратного вызова close
вне конечной точки, чтобы я мог проверить их напрямую. Во-вторых, я бы исключил все глобальные ссылки во всех функциях в пользу параметров функции:
let triggered = (res) => (info) => {
res.write(`\ndata: ${JSON.stringify(info)}\n\n`);
}
let onCloseHandler = (eventEmitter, constants, triggered, res) => () => {
eventEmitter.removeListener(constants.events.TRIGGERED, triggered(res));
}
let updatesHandler = (eventEmitter, constants, triggered) => (req, res) => {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
eventEmitter.addListener(constants.events.TRIGGERED, triggered(res));
req.on('close', onCloseHandler(eventEmitter, constants, triggered, res));
};
router.get('/updates', updatesHandler(eventEmitter, constants, triggered));
С этим кодом тестовые случаи будут выглядеть так:
test("triggered", () => {
let res;
beforeEach(() => {
res = generateFakeRespone();
});
it("should execute res.write with the correct variable", () => {
trigger(res)("whatever");
expect(res.write).to.have.been.called.once;
expect(res.write).to.have.been.called.with(`\ndata: ${JSON.stringify("whatever")}\n\n`);
});
});
test("onCloseHandler", () => {
let res;
let eventEmitter;
let constants;
let triggered;
beforeEach(() => {
res = Math.random();
eventEmitter = generateFakeEventEmitter();
constants = generateFakeConstants();
triggered = generateFakeTriggered();
});
it("should execute eventEmitter.removeListener", () => {
onCloseHandler(eventEmitter, constants, triggered, res);
expect(eventEmitter.removeListener).to.have.been.called.once;
expect(eventEmitter.removeListener).to.have.been.called.with(/*...*/)
});
});
test("updatesHandler", () => {
beforeEach(() => {
req = generateFakeRequest();
res = generateFakeRespone();
eventEmitter = generateFakeEventEmitter();
constants = generateFakeConstants();
triggered = generateFakeTriggered();
});
it("should execute res.writeHead", () => {
updatesHandler(eventEmitter, constants, triggered)(req, res);
expect(res.writeHead).to.have.been.called.once;
expect(res.writeHead).to.have.been.called.with(/*...*/)
});
it("should execute req.on", () => {
//...
});
// more tests ...
});
При таком стиле кодирование и тестирование, у вас есть возможность сделать очень подробный модульный тест. Недостатком является то, что для правильного тестирования требуется гораздо больше усилий.