Skip to content

Instantly share code, notes, and snippets.

@Munawwar
Last active April 9, 2024 21:32
Show Gist options
  • Save Munawwar/c1d024d20b78f19b3714ab09b62a0e1f to your computer and use it in GitHub Desktop.
Save Munawwar/c1d024d20b78f19b3714ab09b62a0e1f to your computer and use it in GitHub Desktop.
Utility to intercept / stub methods of an object for unit test purpose
/*
* This function was created with a realization that once you override a method for mocking
* and run a test, you can't undo the override, because shared code (test runner without
* test isolation) will hold on to closures to the overridden function.
*
* So a solution it to intercept once before all tests, mock for a test and "undoMock()" at
* end of a test will cause the intercept to "proxy" future calls to the original method.
*/
const mocked = new Set();
/**
* @param {any} object
* @param {string} methodName
*/
export function intercept(object, methodName) {
let mockHandler = null;
const originalMethod = object[methodName];
const boundedMethod = object[methodName].bind(object);
// eslint-disable-next-line no-param-reassign
object[methodName] = function interceptedFunction(...args) {
return mockHandler
? mockHandler(boundedMethod, ...args)
: originalMethod.apply(object, args);
};
return {
/**
* @param {(originalMethod: Function, ...args: any[]) => any} mockFunction
*/
mock(mockFunction) {
mockHandler = mockFunction;
mocked.add(this);
},
undoMock() {
mockHandler = null;
mocked.delete(this);
},
/**
* Un-intercepting will not get rid of closures to interceptedFunction
*/
destroy() {
mockHandler = null;
// eslint-disable-next-line no-param-reassign
object[methodName] = originalMethod;
},
};
}
export function undoAllMocks() {
[...mocked].forEach((methods) => methods.undoMock());
}
const { intercept } = require('./intercept');
/**
* @param {any} object
*/
export function interceptAllMethods(object) {
return Object.fromEntries(
Object
.keys(object)
.filter((key) => typeof object[key] === 'function')
.map(
(key) => [key, intercept(object, key)],
),
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment