How to unit test private methods in Typescript

When I tried to do unit testing for private methods in a Class getting error as private methods are only accessible inside the class. Here I added sample snippet for my class and mocha test. Kindly provide me solution to implement unit test for private methods.

Class Name: Notification.ts

class Notification {
 constructor() {}
 public validateTempalte() {
  return true;
 }

 private replacePlaceholder() {
  return true;
 }
}

Unit Test:

import {Notification} from 'Notification';
import * as chai from "chai";

describe("Notification", function(){

  describe('#validateTempalte - Validate template', function() {
      it('it should return success', function() {
        const result = new Notification()
        chai.expect(result.validateTempalte()).to.be.equal(true);
      });
    });
  describe('#replacePlaceholder - Replace Placeholder', function() {
      it('it should return success', function() {
        const result = new Notification()
        // As expected getting error "Private is only accessible within class"
        chai.expect(result.replacePlaceholder()).to.be.equal(true);
      });
    });
});

As a workaround, currently, I am changing access specifier of function replacePlaceholder to public. But I don't think its a valid approach.


Technically, in current versions of TypeScript private methods are only compile-time checked to be private - so you can call them.

class Example {
    public publicMethod() {
        return 'public';
    }

    private privateMethod() {
        return 'private';
    }
}

const example = new Example();

console.log(example.publicMethod()); // 'public'
console.log(example.privateMethod()); // 'private'

I mention this only because you asked how to do it, and that is how you could do it.

Correct Answer

However, that private method must be called by some other method... otherwise is isn't called at all. If you test the behaviour of that other method, you will cover the private method in the context it is used.

If you specifically test private methods, your tests will become tightly coupled to the implementation details (i.e. a good test wouldn't need to be changed if you refactored the implementation).

Disclaimer

If you still test in at the private method level, the compiler might in the future change and make the test fail (i.e. if the compiler made the method "properly" private, or if a future version of ECMAScript added visibility keywords, etc).


A possible solution to omit Typescript checks is to access the property dynamically (Not telling wether its good).

myClass['privateProp'] or for methods: myClass['privateMethod']()


In my case, I use the prototype of the object to get access to a private method. It works well and TS does not swear.

For example:

class Example {
    private privateMethod() {}
}

describe() {
    it('test', () => {
        const example = new Example();
        const exampleProto = Object.getPrototypeOf(example);

        exampleProto.privateMethod();
    })
}

If you use a static method then use exampleProto.constructor.privateMethod();.