Testing private method using spyOn and Jest

Viewed 14862

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

6 Answers

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.

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);

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.

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>();

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);   

Or define interface including method you want to spyOn(), something like:

interface IClassPublic {
  Sum(a: number, b: number): number;
}

then cast object parameter to this type:

jest.spyOn(obj as unknown as IClassPublic, "Sum")
Related