ihaider
ihaider

Reputation: 1350

Mock static functions called in the main function that is being tested

I want to mock some functions within a function I am testing.

I have a class that has several static private functions being called from the so-called mainFunction. I want to particularly test the result of MyClass.functionD (called by mainFunction, which is a private method), therefore, I would like to mock MyClass.functionA, MyClass.functionB and MyClass.functionC to return a default result so that my test can focus on the result of MyClass.fucntionD.

export default class MyClass {

   static mainFunction(paramA: string, paramB: number): boolean {

        if (MyClass.functionA(paramA, paramB)) {
            return false;
        }

        if (!MyClass.functionB(paramA, paramB)) {
            return false;
        }

        if (MyClass.functionC(paramA, paramB)) {
            return false;
        }

        // I need to focus on the result of this function (i.e. private) for my test
        if (MyClass.functionD(paramA)) {
            return false;
        }

        return true;
   }

}

So far, I have tried jest spyOn and some default mock function but I am just lost and cannot proceed as I am really new to typescript / Javascript. Any hint/reference related to how I should proceed would be enough for me. :) Thanks.

Upvotes: 0

Views: 464

Answers (1)

Lin Du
Lin Du

Reputation: 102307

TypeScript public/private keywords only apply to the way TypeScript checks your code - they don't have any effect on the JavaScript output. So you can access these private methods via Bracket notation like MyClass['fucntionA'], that will ignore the type check of TSC. Then you can use jest.spyOn to mock these private methods.

Here is my test strategy for your case:

MyClass.ts:

export default class MyClass {
  static mainFunction(paramA: string, paramB: number): boolean {
    if (MyClass.fucntionA(paramA, paramB)) {
      return false;
    }

    if (!MyClass.fucntionB(paramA, paramB)) {
      return false;
    }

    if (MyClass.fucntionC(paramA, paramB)) {
      return false;
    }

    if (MyClass.fucntionD(paramA)) {
      return false;
    }

    return true;
  }

  private static fucntionA(a, b) {
    return true;
  }

  private static fucntionB(a, b) {
    return false;
  }

  private static fucntionC(a, b) {
    return true;
  }
  private static fucntionD(a) {
    return false;
  }
}

MyClass.test.ts:

import MyClass from './MyClass';

describe('65376946', () => {
  afterEach(() => {
    jest.restoreAllMocks();
  });
  it('should pass', () => {
    const fucntionASpy = jest.spyOn(MyClass as any, 'fucntionA').mockReturnValueOnce(false);
    const fucntionBSpy = jest.spyOn(MyClass as any, 'fucntionB').mockReturnValueOnce(true);
    const fucntionCSpy = jest.spyOn(MyClass as any, 'fucntionC').mockReturnValueOnce(false);
    const fucntionDSpy = jest.spyOn(MyClass as any, 'fucntionD').mockReturnValueOnce(true);

    const actual = MyClass.mainFunction('a', 1);
    expect(actual).toBeFalsy();
    expect(fucntionASpy).toBeCalledWith('a', 1);
    expect(fucntionBSpy).toBeCalledWith('a', 1);
    expect(fucntionCSpy).toBeCalledWith('a', 1);
    expect(fucntionDSpy).toBeCalledWith('a');
  });
});

unit test result:

PASS  examples/65376946/MyClass.test.ts
  65376946
    ✓ should pass (3 ms)

------------|---------|----------|---------|---------|-------------------
File        | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
------------|---------|----------|---------|---------|-------------------
All files   |   42.86 |       50 |      20 |   42.86 |                   
 MyClass.ts |   42.86 |       50 |      20 |   42.86 | 4,8,12,19-34      
------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        4.168 s

Upvotes: 2

Related Questions