question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Angular 9: Spy not tracking/detecting life cycle methods(ngOnInit/ngAfterViewInit)

See original GitHub issue

🐞 bug report

SpyOn not tracking life cycle methods in Angular 9

Affected Package

Don't know.

Is this a regression?

Yes.

Yes. The previous version in which this bug was not present was: Angular 8.

Description

spyOn(component, ‘any life-cycle-method’) not tracking life cycle methods. spyOn(component, ‘any non-life-cycle-method’) works fine. For example:

spyOn('component, 'ngOnInit').and.callThrough(); does not work. spyOn('component, 'fun').and.callThrough(); works.

🔬 Minimal Reproduction

Git hub URL: https://github.com/rohitpratapitm/spyon-failing-for-life-cycle-methods-angular9 Steps To replicate: Run npm run test

Component File

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

  title = 'spyon-failing-for-life-cycle-methods-angular9';

  ngOnInit(): void {
    console.log('I am inside ngOnInit.');
    this.fun();
  }

  fun(): void {
    console.log('I am inside FUN.');
  }
}

Spec File

import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';


describe('AppComponent', () => {

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        AppComponent
      ],
    }).compileComponents();
  }));

  /**
   * This test case FAILS, even though the ngOnInit method is getting called and console log is printed.
   */
  it('should call ngOnInit', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const component = fixture.componentInstance;
    const spyOnNgOnInit: jasmine.Spy = spyOn(component, 'ngOnInit').and.callThrough();
    fixture.detectChanges();
    expect(spyOnNgOnInit).toHaveBeenCalled(); // FAILS
  });

  /**
   * PASSES.
   */
  it('should call fun', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const component = fixture.componentInstance;
    const spyOnFun: jasmine.Spy = spyOn(component, 'fun').and.callThrough();
    fixture.detectChanges();
    expect(spyOnFun).toHaveBeenCalled(); // PASSES
  });
});

–>

🔥 Exception or Error


rsikarwar@DT-00003710 MINGW64 /c/D_Drive/src/spyon-failing-for-life-cycle-methods-angular9 (master)
$ npm run test

> spyon-failing-for-life-cycle-methods-angular9@0.0.0 test C:\D_Drive\src\spyon-failing-for-life-cycle-methods-angular9
> ng test

30% building 10/10 modules 0 active05 06 2020 17:10:45.510:WARN [karma]: No captured browser, open http://localhost:9876/
05 06 2020 17:10:45.525:INFO [karma-server]: Karma v5.0.9 server started at http://0.0.0.0:9876/
05 06 2020 17:10:45.525:INFO [launcher]: Launching browsers Chrome with concurrency unlimited
05 06 2020 17:10:45.535:INFO [launcher]: Starting browser Chrome
05 06 2020 17:10:52.010:WARN [karma]: No captured browser, open http://localhost:9876/
05 06 2020 17:10:52.054:INFO [Chrome 83.0.4103.61 (Windows 10)]: Connected on socket dgm-E-7chY32lAYdAAAA with id 10535314
LOG: 'I am inside ngOnInit.'
Chrome 83.0.4103.61 (Windows 10): Executed 0 of 2 SUCCESS (0 secs / 0 secs)
LOG: 'I am inside FUN.'
Chrome 83.0.4103.61 (Windows 10): Executed 0 of 2 SUCCESS (0 secs / 0 secs)
Chrome 83.0.4103.61 (Windows 10) AppComponent should call ngOnInit FAILED
        Error: Expected spy ngOnInit to have been called.
            at <Jasmine>
            at UserContext.<anonymous> (http://localhost:9876/_karma_webpack_/src/app/app.component.spec.ts:23:27)
            at ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-evergreen.js:364:1)
            at ProxyZoneSpec.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-testing.js:292:1)
Chrome 83.0.4103.61 (Windows 10): Executed 1 of 2 (1 FAILED) (0 secs / 0.347 secs)
Chrome 83.0.4103.61 (Windows 10) AppComponent should call ngOnInit FAILED
        Error: Expected spy ngOnInit to have been called.
            at <Jasmine>
            at UserContext.<anonymous> (http://localhost:9876/_karma_webpack_/src/app/app.component.spec.ts:23:27)
            at ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-evergreen.js:364:1)
LOG: 'I am inside ngOnInit.'
Chrome 83.0.4103.61 (Windows 10): Executed 1 of 2 (1 FAILED) (0 secs / 0.347 secs)
LOG: 'I am inside FUN.'
Chrome 83.0.4103.61 (Windows 10): Executed 1 of 2 (1 FAILED) (0 secs / 0.347 secs)
Chrome 83.0.4103.61 (Windows 10): Executed 2 of 2 (1 FAILED) (0.462 secs / 0.369 secs)
TOTAL: 1 FAILED, 1 SUCCESS
TOTAL: 1 FAILED, 1 SUCCESS

🌍 Your Environment

Angular Version:


$ ng version

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/
    

Angular CLI: 9.1.7
Node: 10.17.0
OS: win32 x64

Angular: 9.1.9
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router
Ivy Workspace: Yes

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.901.7
@angular-devkit/build-angular     0.901.7
@angular-devkit/build-optimizer   0.901.7
@angular-devkit/build-webpack     0.901.7
@angular-devkit/core              9.1.7
@angular-devkit/schematics        9.1.7
@angular/cli                      9.1.7
@ngtools/webpack                  9.1.7
@schematics/angular               9.1.7
@schematics/update                0.901.7
rxjs                              6.5.5
typescript                        3.8.3

Anything else relevant?

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:5
  • Comments:10 (4 by maintainers)

github_iconTop GitHub Comments

5reactions
miquelnezcommented, Jul 1, 2020

I’ve the same problem. After the update from angular 8 to angular 9, several unit tests are broken because we can’t spy any of the component’s life hooks.

const spyOnInit = spyOn(nestedComponent, 'ngOnInit').and.callThrough();
const spyTabActive = spyOn(nestedComponent, 'tabActive').and.callThrough();
fixture.detectChanges();
expect(spyOnInit).toHaveBeenCalledBefore(spyTabActive);

Expected spy ngOnInit to have been called.

And, it really does everything as expected. But the tests fails

2reactions
MarcusRiemercommented, Feb 23, 2021

I am using ngOnChanges to push changes to @Input() variables into a RxJS Subject:

// Used to feed the Subject for the permission request
ngOnChanges(changes: SimpleChanges): void {
  if (changes["payload"]) {
    this._payload$.next(this.payload);
  }
}

In spec code like the following, ngOnChanges is never called:

let fixture = TestBed.createComponent(PayloadComponent);
let component = fixture.componentInstance;

component.payload = req;

fixture.detectChanges();

So as far as I understand this ist not only about spying, but also about more fundamental logic. For me this means I would currently have to create a virtual, spec-only component to reliably have ngOnChanges called as it would be called in a “real” environment.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Spy not tracking/detecting life cycle methods(ngOnInit ... - Reddit
Git hub issue : SpyOn not tracking life cycle methods in Angular 9 Affected Package Don't know. Is this a regression? Yes. Yes....
Read more >
Lifecycle hooks - Angular
The Spy example demonstrates how to use the hook method for directives as well as components. The SpyDirective implements two hooks, ngOnInit() and...
Read more >
unit testing for ngAfterViewInit? - angular - Stack Overflow
You can invoke lifecycle hooks programmatically using the component instance, like: ... Consider using the new approach to testing:
Read more >
Testing Angular lifecycle hooks | Damir's Corner
There's no specific guidance for testing Angular lifecycle hooks in the component testing scenarios covered by the Angular documentation.
Read more >
Lifecycle Hooks • Angular - codecraft.tv
Using life-cycle hooks we can fine tune the behaviour of our components during creation, update and destruction. We use the ngOnInit hook most...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found