Question:
Unit Test Angular Standalone Component, Overriding Provider not used

Problem

I have an angular component, using a class that I want to mock in the unit test. So I override this in the provider-section of my test. But the component still calls the real class and I get an error.


This worked fine in older projects without standalone components, but I think I need to do something different for standalone components. But I couldn't figure out what :-(


I simplified it to this test case:


import { ComponentFixture, TestBed } from '@angular/core/testing';

import { IonicModule, ModalController } from '@ionic/angular';

import { BrowserModule } from '@angular/platform-browser';

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


// Dummy Standalone Component, just a single method that uses the ionic ModalController

@Component({

    selector: 'app-test-dialog',

    template: '',

    imports: [

        IonicModule

    ],

    standalone: true

})

export class TestDialogComponent {


    constructor(private modalCtrl: ModalController) {


    }


    async close() {

        await this.modalCtrl.dismiss();

    }


}



// Test, should override the dismiss method of the ModalController

describe('TestDialogComponent', () => {

    let component: TestDialogComponent;

    let fixture: ComponentFixture<TestDialogComponent>;


    beforeEach(async () => {

        await TestBed.configureTestingModule({

            imports: [

                BrowserModule,

                IonicModule.forRoot(),

                TestDialogComponent

            ],

            providers: [

                {

                    // provide our own ModalController

                    provide: ModalController, useValue: {

                        dismiss: () => Promise.resolve()

                    }

                }

            ]

        }).compileComponents();

        fixture = TestBed.createComponent(TestDialogComponent);

        component = fixture.componentInstance;

    });


    // this should call the provided mock class

    // but I get 'overlay does not exist thrown' 

    // because it calls the real method :-(

    it('close closes the dialog', async () => {

        const modalController = TestBed.inject(ModalController);

        const dismissSpy = spyOn(modalController, 'dismiss');

        await component.close();

        expect(dismissSpy).toHaveBeenCalled();

    });


});


Solution

To override the ModalController provider in your test, you would do the following:



it('close closes the dialog', async () => {

  // Override the ModalController provider for the TestDialogComponent component

  TestBed.overrideComponent(TestDialogComponent, {

    providers: [

      {

        provide: ModalController,

        useValue: {

          dismiss: () => Promise.resolve()

        }

      }

    ]

  });


  // Create a fixture for the TestDialogComponent component

  const fixture = TestBed.createComponent(TestDialogComponent);

  const component = fixture.componentInstance;


  // Call the close method on the component

  await component.close();


  // Expect the dismiss method on the mock ModalController to have been called

  expect(spyOn(TestBed.inject(ModalController), 'dismiss')).toHaveBeenCalled();

});


Suggested blogs:

>What is the Idiomatic way to write a Typescript function with casting

>Why Redux-toolkit payload don't reconigze type in TypeScript?

>TypeScript: Define a type that refers type parameter from another line?

>Solve return type on TypeScript with boolean check doesn't seem to work

>How to fix TS2551: Property toSpliced does not exist on type Array

>Making an argument required if generic interface as no properties

>How to make argument required if generic interface as no properties?

>Cause a type error when a function returns any in TypeScript?

>Library isn’t work in Nestjs useGlobalFilters with library in TypeScript

>How to get the last cell with data for a given column in TypeScript?

>Ignore requests by interceptors based on request content in TypeScript?

>Create data with Typescript Sequelize model without passing in an id?

>How to delete duplicate names from Array in Typescript?


Nisha Patel

Nisha Patel

Submit
0 Answers