Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 313
matteo Avatar asked Apr 06 '17 21:04

matteo


People also ask

How do you test private functions in react?

You can't test private functions, and they're not supposed to be tested in isolation as they're supposed to be part of the internal implementation. If you want to test it in isolation, then export it. If you think it's private and should not be exported, then you need to test through your other code.

Should you mock private methods?

Mocking techniques should be applied to the external dependencies of the class and not to the class itself. If mocking of private methods is essential for testing our classes, it usually indicates a bad design.

How do you mock a real function in Jest?

There are two ways to mock functions: Either by creating a mock function to use in test code, or writing a manual mock to override a module dependency.

How do you Mock a module in jest?

jest.mock () is called with one required argument - the import path of the module we're mocking. It can also be called with an optional second argument - the factory function for the mock. If the factory function is not provided, Jest will automock the imported module.

What is jest mocking and why should you use it?

When testing JavaScript code using Jest, sometimes you may find yourself needing to mock a module. Whether it’s because the module or the functions it exports are irrelevant to the specific test, or because you need to stop something like an API request from trying to access an external resource, mocking is incredibly useful.

How to mock a private function in Java?

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 } }

What is mockimplementation () method in jest?

The mockImplementation () method is called with the new implementation as its argument. The new implementation will then be used in place of the previous one when the mock is called. We can combine this with jest.mock () factory functions to create mocked modules that contain mocked functions.


3 Answers

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');     })     ...   }) }) 
like image 136
matteo Avatar answered Sep 19 '22 09:09

matteo


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();
  });
});
like image 29
Mikhail Savich Avatar answered Sep 22 '22 09:09

Mikhail Savich


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.

like image 36
Andreas Köberle Avatar answered Sep 22 '22 09:09

Andreas Köberle