Search code examples
angularunit-testingng-mocks

Angular test - set up a spy on a function of the SUT component before the component is created by TestBed


I have an Angular component I am writing tests for. The SUT component has a function I need to spy on (not ideal as noted further below). I want to set up the TestBed so that the function already has a spy assigned when TestBed creates the component.

I know how to spy on the function once the SUT component has been created. But I suspect there is a way to do that declaratively, I just can't find it. One reason I need that for is that if the SUT component executes some functions right after the component is created (e.g. from the constructor), I need the spies on those functions to be in place before the SUT is created.

I also realize that SUT shouldn't normally have its elements mocked/spied, and I actually ended up rewriting my tests accordingly. But I am still curious whether the "SUT declarative spying" is possible.

I tried to achieve this with TestBed.configureTestingModule.overrideComponent but that doesn't provide access to individual component functions to override.

I also tried ng-mocks, hoping MockBuilder might have support for mocking one specific function of the SUT component, but no luck there either.


Solution

  • The only way you can spy a method of SUT is to update its prototype before the creation of an instance of it:

      let backup: any;
      beforeEach(() => {
        backup = TargetComponent.prototype.func;
        TargetComponent.prototype.func = jasmine.createSpy().and.returnValue('mock');
      });
    
      afterEach(() => {
        TargetComponent.prototype.func = backup;
      });
    

    An example is here: https://codesandbox.io/s/objective-scott-euy6dz?file=/src/test.spec.ts