Last active
April 9, 2024 21:32
-
-
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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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()); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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