Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest/Typescript: Mock class dependencies in Jest and Typescript

I have class B which is dependent on class A. I want to test a method of class B which is internally calling a method of class A. Now, I want to unit test my method of class B by mocking class A.

My code structure:

class A {
  getSomething() {
     return "Something";
  }
}


class B {
  constructor(objectOfClassA: A) {
      this._objectOfClassA = objectOfClassA;

 }

 functionofClassBToTest() {
     const returnValueFromClassA = this._objectOfClassA.getSomething();

     return returnValueFromClassA;
 }
}

What I have tried so far:

import ....
import { mocked } from 'jest-mock';

jest.mock("./A", () => {
    return {
        A: jest.fn().mockImplementation(() => {
            return {
                getSomething: getSomethingMock
            }
        })
    };
});

const getSomethingMock = jest.fn().mockImplementation(() => {
    return "Mock value";
});

const mockA = mocked(A, true);

test("test functionofClassBToTest", () => {
    const classBToTest = new B(mockA);

    expect(classBToTest.functionofClassBToTest.toStrictEqual("Mock value");
});


This is the error that I am getting:

TypeError: this._objectOfClassA.getSomething is not a function

Note: I don't want to initialize an object of class A inside my test function. I only want to mock the class.

I also found some previous posts on SO : Post1 and Post2 but nothing worked.

UPDATE: This problem got solved thanks to James's answer below. For mocking classes with private members, I have asked another SO Question. Please do read it.

like image 543
aniket singh Avatar asked Jan 02 '26 07:01

aniket singh


1 Answers

Given that Typescript is structurally typed, it should be possible to simply construct an object literally that matches the interface of the A class and pass that into class B.

For example:

const mockA: jest.Mocked<A> = {
  getSomething: jest.fn()
};

const b = new B(mockA);

expect(mockA.getSomething)
    .toHaveBeenCalled();

This should not generate type errors given mockA exactly matches the interface of class A.

To mock the return value of A’s methods, refer to mocking individual functions with Jest.

This proves to be simpler and more succinct than attempting to mock the entire module. Since you’ve used IoC as a pattern, mocking the module is not necessary.

You also have a typo. Class B assigns to an instance variable with only one underscore but then calls the method on an instance variable with two underscores.

like image 192
James Dunne Avatar answered Jan 03 '26 20:01

James Dunne



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!