This came up when doing development a work. An experienced programmer who was new to TypeScript asked how to test a private static method. For many languages, you wouldn't test a private method directly; only indirectly through other methods.
This private static method on a class, seemed test worthy to her. So, how do you do it? There are a few ways.
The Setup
Since, my team works in Angular, I'll assume we're using an Angular project with Karma and Jasmine. Let's create the class:
2 private static staticMethod(input: string): string {
3 return input;
4 }
5}
I have a super simple method here; one that accepts a string input and returns it. The method is private and static. This type of structure would generally be used for a utility method inside the class; which is most likely called by other public methods in the same class.
But, for the purposes of testing, we want to call the method directly.
The Test Structure
Let's create the test structure:
2 it('should call private method', () => {
3 const input = 'This is a test';
4 });
5});
There is a describe block; and a single test. Inside the test I created a simple constant, that we can use to send into the method and out of the method.
Call the method directly
First, you can call the method directly:
In JavaScript there is no such thing as a private methodl. You will get compiler errors, here though:
The error is:
TS2341: Property 'staticMethod' is private and only accessible within class 'ClassWithStaticMethod'.
Our code will work in the browser, but will not compile in TypeScript. You may remember from last week, that we know how to TypeScript to ignore the error, with the ts-ignore directive:
2expect(ClassWithStaticMethod.staticMethod(input)).toBe(input);
Now we are good to go. No code errors and this works.
Use Object Array Notation with a String Literal
We can also access properties using object array notation:
Instead of using the property notation to get the method, like we did in the previous section, we are listing the name of the method inside the square brackets.
Unfortunately, this will also give you an error:
The error is:
TSLint: object access via string literals is disallowed(no-string-literal
This error relates to Angular's default TSLint settings, so not an explicit TypeScript error. Still something that will make it difficult. Last week I also wrote about a way to ignore TS Lint errors, using tslint:disable-next-line. Add that before the line:
2expect(ClassWithStaticMethod['staticMethod'](input)).toBe(input);
Use Object Array Notation with a variable
A third option is to use the Object Array Notation with a variable. Then we don't have to mess around TSlint or TypeScript settings:
2 expect(ClassWithStaticMethod[methodName](input)).toBe(input);
Final Thoughts
As with many programming challenges, there are multiple ways to tackle and solve them. I hope you learned something about testing private methods that will help you solve your issue.