'Testing private method using spyOn and Jest

My functions in Calculator class is private and I can't test in this way,

describe('calculate', function() {
  it('add', function() {
    let result = Calculator.Sum(5, 2);
    expect(result).toBe(7);   
  });

  it('substract', function() {
    let result = Calculator.Difference(5, 2);
    expect(result).toBe(3);
  });
});

my class:

export default class calculator {
  private Sum(a: number, b: number): number {
    let c = a + b;
    return c;
  }

  private Difference(a: number, b: number): number {
    let c = a - b;
    return c;
  }
}

how can I modify this test with using spyOn on private methods?

thanks for any help



Solution 1:[1]

you can try jest.spyOn for get implementation of private method

Class

export default class Calculator {
  private Sum(a: number, b: number): number {
    let c = a + b;
    return c;
  }
}

Test

const handleErrorSpy = jest.spyOn(Calculator.prototype, 'Sum');
const getSumImplementation = handleErrorSpy.getMockImplementation();

expect(getSumImplementation(1, 2)).toEqual(3);

Solution 2:[2]

If it's a private data you can't get access to, then you shouldn't test it because it's an internal implementation that might be changed.

You need to cover public interface of your classes that uses this class inside to ensure that they work correctly, how they work inside is their own business.

Otherwise you need to make it public, or at least to pass it as a dependency so you could use a mocked version of it.

Solution 3:[3]

In Typescript it doesn't allow you to test the private method. So you need something to escape from this behavior. What you can do is something like this

let result = (Calculator as any).Sum(2,3);
expect(result).toBe(5);

I hope that will solve your problem.

Solution 4:[4]

The visibility of TypeScript private methods is checked at compilation time. They can be accessed in tests when type checks are disabled. This includes spying on private methods with spyOn but they don't benefit from being spies when called directly.

Calculator is a class, it should be instantiated in order to access its methods:

let calculator = new Calculator();
let result = calculator['Sum'](5, 2);
expect(result).toBe(7);   

Solution 5:[5]

The easiest solution, to spy on your 'Sum' method of Calculator class, I came around would be:

jest.spyOn(calculator as any, 'Sum').<do-something>();

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 Skraloupak
Solution 2 satanTime
Solution 3 Abdullah Al Mahmud
Solution 4 Estus Flask
Solution 5 Pauli