Encountering an error when cleaning up an Angular component due to the unsubscribe process during

While testing a component that subscribes to router params, all tests pass and everything works smoothly. However, upon checking the console, there is an error message:

Error during cleanup of component ApplicationViewComponent localConsole.(anonymous function) @ context.js:232

Do you have any idea why this error occurs?

I found that removing the unsubscribe() from the ngOnDestroy() method resolves the error.

Is karma/jasmine automatically handling unsubscribe()?

Below are the details of the component and its associated tests.

Component

 Copying code... 

Component spec file

 Copying code... 

service.stub

 Copying code... 

Answer №1

One of the challenges faced in Angular development is the "Error during component cleanup" error message. This occurs when ngOnDestroy() is triggered, but this.routeSubscription is undefined due to ngOnInit() not being invoked beforehand. This means that no subscription was made to the route. To address this issue, it is essential to follow the guidance provided in the Angular testing tutorial. According to this resource, the component is not fully initialized until fixture.detectChanges() is called for the first time.

The solution lies in including fixture.detectChanges() in the beforeEach() block immediately after invoking createComponent. This step can be performed at any point after setting up the fixture. By doing so, it guarantees that the component is completely initialized, thus ensuring proper behavior during component cleanup.

Answer №2

It is necessary to adjust your ngOnDestroy method in the following manner :

ngOnDestroy() {
  if ( this.routeSubscription)
    this.routeSubscription.unsubscribe();
}

Answer №3

I found that the issue was resolved by destroying the component after every test. You may want to consider incorporating this into your describe function:

afterEach(() => {
  fixture.destroy();
})

Answer №4

I find myself facing a situation where I need to test a function in my component independently of the component's context.

This is the approach that proved successful for me:

afterEach(() => {
  spyOn(component, 'ngOnDestroy').and.callFake(() => { });
  fixture.destroy();
});

Answer №5

You should include the following code snippet in your TestBed.configureTestingModule:

teardown: { destroyAfterEach: false },

By adding this line, your configuration will appear as follows:

beforeEach(async () => {
        await TestBed.configureTestingModule({
            declarations: [<Your component here>],
            imports: [<Your imports here>],
            providers: [<Your providers here>],
            teardown: { destroyAfterEach: false },
        }).compileComponents();
    });

Answer №6

My experience was somewhat similar, with a few differences that could be useful for others. During my unit testing using Jasmine/Karma, I encountered the following error:

'ERROR: 'Error during cleanup of component','

After some investigation, I realized this issue stemmed from not handling my observables correctly, specifically lacking an error function. The solution was to include an error function like so:

this.entityService.subscribe((items) => {
      // Do some work
},
error => {
    this.errorEventBus.throw(error);
});

Answer №7

In continuation of the answer provided by @David Brown, I found success with the following code snippet.

      .subscribe(res => {
          ...
        },
        error => Observable.throw(error)
      )

Answer №8

According to the insights shared by @randomPoison, the error arises when the component utilizing unsubscribe is not initialized. To tackle this issue in the spec file of the corresponding component, executing fixture.detectChanges() proves to be a viable solution.

In situations where we are working with a FooComponent that generates BarComponent, and the latter employs unsubscribe within its ngOnDestroy, it is crucial to ensure proper mocking is implemented.

An alternative method for handling subscription cleanup that is more declarative and less prone to these issues is recommended. Below is an illustration:

export class BazComponent implements OnInit, OnDestroy {
  private unsubscribe$ = new Subject();

  ngOnInit(): void {
    someObservable$
      .pipe(takeUntil(this.unsubscribe$))
      .subscribe(...);
  }

  ngOnDestroy(): void {
    this.unsubscribe$.next();
    this.unsubscribe$.complete();
  }
}

For further details on this approach, refer to this resource

Answer №9

To resolve this issue, there are two steps that need to be taken.

Step 1: Insert fixture.detectChanges(); within the beforeEach() function.
Step 2: Include the following code snippet to ensure the component is properly cleared.

afterEach(() => {
        fixture.destroy();
      });

Answer №10

My particular issue stemmed from a mistake in the template. The problem lied within the child component's ngDestroy function, which was failing to be destroyed due to my attempt at setting a readonly property. I recommend examining your child components to ensure they are being properly destroyed.

Answer №11

In order to resolve this issue, I made a simple adjustment within the ngOnDestroy method of my component. I enclosed both the store dispatch and unsubscribe functions in a try-catch block.

ngOnDestroy(): void {
 try {
  this.store.dispatch(new foo.Bar(this.testThing()));
  if(this.fooBarSubscription) {
   this.fooBarSubscription.unsubscribe();
  }
 } catch (error) {
   this.store.dispatch(new foo.Bar(this.testThing()));
  }
}

Answer №12

During my testing, I encountered a situation where I had a component with several @Input properties. To initialize one of the properties as an empty array, I assigned [] to component.xyz within the beforeEach block. This action inadvertently led to a problem in the testing process.

Answer №13

While setting one of the services variables to undefined, I encountered an error message. This particular variable contains the ID of the currently active entity being edited. Diving into the setter method, I realized that it was expecting a parent entity to be set... and since my tests did not include this step, it resulted in an error.

The code snippet causing the issue looked like this:

 ngOnDestroy(): void {
    this.subs.forEach(s => s.unsubscribe());
    this.xxxEditService.activeYYY = undefined; // The setter requires a parent entity to be set
 }

To resolve this issue, I added a mock entity in my test file:

providers: [
 {
   provide: xxxEditService,
   useValue: {
     parentEntity: {} as Parent,
     activeYYY: -1   // id
   }
}

TLDR: Errors were occurring during clean up due to non-valid presets, such as null or undefined references.

Answer №14

The reason for the problem was a simple human mistake.

In my specific situation, I overlooked adding the sendC method (which was a newly added method to ABCComponent) to the list of methods in the dependent spy component. To illustrate:

let abcComponent: jasmine.SpyObj<ABCComponent>
///
beforeEach(async () => {

    abcComponent = jasmine.createSpyObj('ABCComponent', [
      'sendA$',
      'sendB$',
      'sendC$' // I initially missed this and encountered the 'Error during cleanup of component' failure. Once I included it, the issue was resolved.
    ])

    await TestBed.configureTestingModule({
      declarations: [AComponent],
      providers: [
        AState,
        APipe,
        BPipe,
        
        { provide: ABCComponent, useValue: abcComponent },
        { provide: Router, useValue: routerSpy },
        { provide: NavigationService, useValue: navigationServiceSpy},
      ],
      imports: [ABCModule]
    })
      .compileComponents()
      abcComponent = TestBed.inject(ABCComponent) as jasmine.SpyObj<ABCComponent>
  })

By rectifying this oversight, not only did I fix my own issue but hopefully, it will help resolve similar problems for others too!👍

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue occurs where the system is unable to recognize a defined variable, despite it being clearly defined

I keep encountering an error message stating that my variable is not defined, even though I have clearly defined it just a few lines above where the error occurs. The reason behind this error is baffling to me, as I cannot identify any potential triggers ...

Avoid incorporating unicode characters in Angular 4

How can I prevent users from using unicode characters in a text field in my front-end developed with Angular 4 framework? For example: ½ -> U+00BD ('onehalf') ...

The nest build process encounters errors related to TypeScript in the @nestjs/config package, causing it

Encountering several issues related to @nestjs/config, causing the npm build command to fail. However, npm run start:dev is still functional despite displaying errors. See below for screenshots of the errors and environment: https://i.sstatic.net/Wxkkn.png ...

I am having trouble getting the bs-stepper to function properly within my Angular project

I am currently facing issues with the bs-stepper module in my Angular code. It is not functioning as expected and is throwing errors. Here is a snippet of my code: export class FileUploadProcessComponent implements OnInit { import Stepper from 'b ...

Achieving the incorporation of multiple components within a parent component using Angular 6

Within parent.component.html The HTML code I have implemented is as follows: <button type="button" class="btn btn-secondary (click)="AddComponentAdd()">Address</button> <app-addresse *ngFor="let addres of collOfAdd" [add]="addres">< ...

Display a React functional component

Greetings, friends! I recently created a React app using functional components and now I am looking to print a specific page within the app. Each page is its own functional component, so I was wondering if it's possible to print a component individual ...

Problem with Angular app not loading in IE 11 due to ES6 targeting

I have encountered an issue while developing a new application with IE11 as the target browser. When I set the target to es6, the app fails to load and displays the error shown below. https://i.stack.imgur.com/FL8BG.png However, when I switch the target ...

The specified attribute "matListItemTitle" is invalid in this context

Having trouble incorporating a list from Angular Material into an Angular project. WebStorm is showing the error mentioned in the title above. I came across the problem here, but in this scenario, I am unable to use matListItemTitle as a dynamic parameter ...

Navigating the parent scope in Angular using TypeScript

Is there a way to access the parent Controller's scope from within the TypeScript class? Here is the code snippet: export class EntityOverviewCtrl extends AbstractCtrl { public static $inject = ["$state", "$http", "CurrentSession"]; publi ...

Ways to reuse test cases across different test suites in Protractor

There are some shared test cases that can be utilized across different test suites. For example, suppose suite x and suite y both require the same set of test cases to function properly. To address this, a separate .js file containing the shared code has ...

Can a lightweight database be utilized in a Nativescript project focused on code sharing?

Currently, I am in the process of launching a new code sharing project using nativescript. My main goal is to create an offline app suitable for both tablets and desktops. I have successfully implemented code sharing following this guide: . Now, my focus ...

Strategies for displaying error messages in case of zero search results

I am currently developing a note-taking application and facing an issue with displaying error messages. The error message is being shown even when there are no search results, which is not the intended behavior. Can someone help me identify what I am doing ...

Modifying styles/css in Angular2 using JavaScript results in a temporary change in styles before ultimately reverting back to the original styles

Recently, I encountered an issue while trying to change styles for some elements in Angular 2 using JavaScript. Interestingly, when the view is loaded, the height is initially set to maxHeight = 100, but after a few milliseconds, it reverts back to the o ...

Strategies for transferring ngModel data from child components to parent components (child to parent to grandparent)

I am currently working on multiple parent components that utilize template-driven forms: user-data.components.ts admin-data.components.ts customer-data.components.ts Each of these parent components have form elements that are child components utilizing NG ...

When Typescript compiles to JavaScript, it may result in code that appears to be a function

In the following typescript code snippet: export enum UID { FACTORY, ROBOT } we see how it compiles to javascript: (function (UID) { UID._map = []; UID._map[0] = "FACTORY"; UID.FACTORY = 0; UID._map[1] = "ROBOT" ...

Angular 2 destroy outlet-content and refresh the view

Is there a method in Angular 2 to remove a component that was automatically created within a router-outlet? I am looking to destroy it so that a new one is generated when I navigate back to that outlet (or is there a way to reload the outlet?). ...

Is it possible to downgrade the AngularCLI version from 1.0.0-beta.30 to 1.0.0-beta.26 on a global scale?

Following the execution of the commands below: npm uninstall -g angular-cli @angular/cli npm cache clean npm install -g <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2849464f5d44495a054b4441681906180618054a4d5c49061a1e">[e ...

The Firebase storage percentChanges() method is throwing a NaN error

I want to create a Firebase storage service using an Angular client to handle user profile image uploads. This service should return two observables: uploadProgress$ and downloadUrl$. The uploadProgress$ observable will store the value from percentChanges ...

Setting up SonarQube for an AngularJS project utilizing Typescript is a breeze with these simple steps!

After setting up SonarQube and SonarScanner and successfully scanning my project, I noticed that all metrics appear on my screen except for code coverage, which remains at 0%. What could be causing this issue? #----- Default SonarQube server sonar.host.url ...

What is the method for utilizing OR statements in Playwright assert?

How can I verify whether the text content is either one or two using Playwright? await expect(this.header).toHaveText('one').or('two') Is there a way to achieve this functionality in Playwright? Additionally, can this feature be inco ...