node.jsunit-testingmockingjasminejasmine-node

Unable to spy on a class instance inside another class


I'm instantiating the service class inside the controller class, and the log method of the service is been used in the controller.

In spec file, I'm adding spy on the log method but the spy is not been called.

Here is my code

test.service.ts

export class TestService {
  public log(msg: string): void {
    console.log(msg);
  }
}

test.controller.ts

import { TestService } from "../service/cart.service";

export class CartController {
  private testService: TestService;

  constructor() {
    this.testService = new TestService();
  }
  public testFx():void {
    this.testService.log("Here is a dummy msg.")
  }
}

test.controller.spec.ts

import { TestController } from "./test.controller";
import { TestService } from "./test.service";
describe("Testing controller", () => {
  private testController: TestController = new TestController();
  private testService: TestService = new TestService();

  it ("test function", () => {
    spyOn(testService, "log");
    testController.testFx();
    expect(testService.log).toHaveBeenCalled();
  });
})

Error: - Expected spy log to have been called.


Solution

  • Instead of creating a new class instance,

     private testController: TestController = new TestController();
     private testService: TestService = new TestService();
    
     it ("test function", () => {
     spyOn(testService, "log");
    

    you can use escape hatch for it.

    Try this:

     private testController: TestController = new TestController();
     it ("test function", () => {
     spyOn(testController["testService"], "log");
    

    Since the private, protected and public are the concept of typescript's syntactic sugar it has nothing to do when code compiles to javascript. The more explaining answer is here.