'Is there any way to mock private functions with Jest?
The ES6 module that I want to test looks as follows:
function privateFunction() {
...
}
export function publicFunction() {
... does something ...
privateFunction()
... does something else ...
}
I am using JEST for my unit tests and I am trying to find a way to test publicFunction
and avoiding the execution of privateFunction
by mocking it but I couldn't succeed in the mock attempt. Any idea?
Solution 1:[1]
I found a way to mock my private function by using the babel-plugin-rewire
module.
In package.json
I have the following:
"devDependencies": {
...
"babel-plugin-rewire": "1.0.0-beta-5",
"babel-jest": "18.0.0",
...
In .babel.rc
I have the following:
{
"presets": [
"es2015",
"stage-0",
"react"
],
"env": {
"test": {
"plugins": [
"babel-plugin-rewire"
]
}
},
...
At this point I was able to mock the private function:
import * as moduleToTest from './moduleToTest.js'
describe('#publicFunction', () => {
it('mocks private function', () => {
moduleToTest.__Rewire__('privateFunction', () => {
console.log('I am the mocked private function');
})
...
})
})
Solution 2:[2]
If you want to mock a private function, try to use the prototype. For example, you need to mock privateFunction of the following class:
export class Module {
public publicFunction() {
// do something
this.privateFunction();
// do something
}
private privateFunction() {
// do something
}
}
So you should use Module.prototype in the jest.spyOn function.
import { Module } from "./my-module";
describe('MyModule', () => {
it('tests public function', () => {
// Arrange
const module = new Module()
const myPrivateFunc = jest.spyOn(Module.prototype as any, 'privateFunction');
myPrivateFunc.mockImplementation(() => {});
// Act
module.publicFunction();
// Assert
expect(myPrivateFunc).toHaveBeenCalled();
});
});
Solution 3:[3]
There is no way through the nature of JavaScript. The function is bound to the scope of the module, so there is no way to know that this function exists from the outside, so no way to access the function and in the end no way to mock it.
Maybe more important, you should not test on the internals of the object under test but only the public API. Cause that is everything that counts. No one cares how stuff is done internally as long as the public API stays stable.
Solution 4:[4]
Another option would be an explicit cast:
const spy = jest.spyOn((someInstance as unknown) as { privateMethod: SomeClass['privateMethod'] }, 'privateMethod');
It's a bit lengthy, but it has the advantage of keeping the typing of the private method for subsequent checks like spy.hasBeenCalledWith(...)
.
Solution 5:[5]
The most simple way I found to spyOn
private methods using ts-jest
.
First assume following example class with private method doStuff
you wanna spy on:
class Example{
private doStuff(): void {
...doing stuff
}
}
const example = new Example();
Then is how you write a spy
jest.spyOn(example as any, 'doStuff');
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Audwin Oyong |
Solution 2 | henrebotha |
Solution 3 | Andreas Köberle |
Solution 4 | Rene Hamburger |
Solution 5 | Pauli |