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:

view plain print about
1export class ClassWithStaticMethod {
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:

view plain print about
1describe('ClassWithStaticMethod', () => {
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:

view plain print about
1expect(ClassWithStaticMethod.staticMethod(input)).toBe(input);

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:

view plain print about
1// @ts-ignore
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:

view plain print about
1expect(ClassWithStaticMethod['staticMethod'](input)).toBe(input);

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:

view plain print about
1// tslint:disable-next-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:

view plain print about
1const methodName = 'staticMethod';
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.