From 80ee2272bac19d1b2bc41c92a0a48bcbe67691c4 Mon Sep 17 00:00:00 2001 From: Henry Tsai Date: Fri, 5 Jul 2024 11:27:15 -0700 Subject: [PATCH] Better approach to testing process handlers --- src/process-handlers.ts | 8 +++---- tests/process-handler.spec.ts | 32 +++++++++++++++++++++------- tests/scenarios/registration.spec.ts | 4 ---- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/process-handlers.ts b/src/process-handlers.ts index e9f1b66..b9de6e6 100644 --- a/src/process-handlers.ts +++ b/src/process-handlers.ts @@ -59,8 +59,8 @@ export const unsetProcessHandlers = (handlers: ProcessHandlers): void => { sigtermHandler } = handlers; - process.off('unhandledRejection', unhandledRejectionHandler); - process.off('uncaughtException', uncaughtExceptionHandler); - process.off('SIGINT', sigintHandler); - process.off('SIGTERM', sigtermHandler); + process.removeListener('unhandledRejection', unhandledRejectionHandler); + process.removeListener('uncaughtException', uncaughtExceptionHandler); + process.removeListener('SIGINT', sigintHandler); + process.removeListener('SIGTERM', sigtermHandler); }; \ No newline at end of file diff --git a/tests/process-handler.spec.ts b/tests/process-handler.spec.ts index 9ee7106..708c8fb 100644 --- a/tests/process-handler.spec.ts +++ b/tests/process-handler.spec.ts @@ -2,28 +2,25 @@ import { expect } from 'chai'; import sinon from 'sinon'; import { config } from '../src/config.js'; +import type { Dwn } from '@tbd54566975/dwn-sdk-js'; import { DwnServer } from '../src/dwn-server.js'; import { getTestDwn } from './test-dwn.js'; import { Poller } from './poller.js'; describe('Process Handlers', function () { + let dwn: Dwn; let dwnServer: DwnServer; let processExitStub: sinon.SinonStub; beforeEach(async function () { - const testDwn = await getTestDwn(); - dwnServer = new DwnServer({ dwn: testDwn, config: config }); + const dwn = await getTestDwn(); + dwnServer = new DwnServer({ dwn, config: config }); await dwnServer.start(); processExitStub = sinon.stub(process, 'exit'); }); afterEach(async () => { await dwnServer.stop(); - console.log('server stop in Process Handlers tests'); - - process.removeAllListeners('SIGINT'); - process.removeAllListeners('SIGTERM'); - process.removeAllListeners('uncaughtException'); processExitStub.restore(); }); @@ -45,16 +42,35 @@ describe('Process Handlers', function () { }); }); - it('should log an error for an uncaught exception', function () { + it('should log an error for an uncaught exception', async () => { + + // IMPORTANT: this test is a bit tricky to write because + // existing process `uncaughtException` listener/handler will result will trigger an error when we force an `uncaughtException` event + // causing the test to fail. So we need to remove the existing listener and add them back after the test. + // To be in full control of the test, we also create the DWN server (which adds it's own `uncaughtException` listener) + // AFTER removing the existing listener. + await dwnServer.stop(); + + // storing then removing existing listeners and adding back at the very end of the test + const existingUncaughtExceptionListeners = [...process.listeners('uncaughtException')]; + process.removeAllListeners('uncaughtException'); + + dwnServer = new DwnServer({ dwn, config: config }); + await dwnServer.start(); + const consoleErrorStub = sinon.stub(console, 'error'); // Stub console.error const errorMessage = 'Test uncaught exception'; const error = new Error(errorMessage); process.emit('uncaughtException', error); // Ensure console.error was called with the expected error message + console.log('console.error call count', consoleErrorStub.callCount); expect(consoleErrorStub.calledOnce).to.be.true; // Restore the original console.error consoleErrorStub.restore(); + + // add back original listeners + existingUncaughtExceptionListeners.forEach(listener => process.on('uncaughtException', listener)); }); }); diff --git a/tests/scenarios/registration.spec.ts b/tests/scenarios/registration.spec.ts index 7e2bc83..a826bc0 100644 --- a/tests/scenarios/registration.spec.ts +++ b/tests/scenarios/registration.spec.ts @@ -35,10 +35,6 @@ if (!globalThis.crypto) { globalThis.crypto = webcrypto; } -console.log = (): void => {}; -console.error = (): void => {}; -console.info = (): void => {}; - describe('Registration scenarios', function () { const dwnMessageEndpoint = 'http://localhost:3000'; const termsOfUseEndpoint = 'http://localhost:3000/registration/terms-of-service';