Home > Software design >  How to override Provider in Angular 13 for angular testing Jasmine Karma?
How to override Provider in Angular 13 for angular testing Jasmine Karma?

Time:06-17

So i've looked at many issues online related override Provider but not getting success. Showing in this code i have already working in angular version 7 this test case working fine.When i upgrade to angular version 13 than test cases are failing and getting errors like this. This error relate to overrideProviders when code comment in component than all test case success Otherwise failed. I have to created mock several times the same service with different mocks.

Error: Actions must be plain objects. Use custom middleware for async actions. enter image description here

Here Is package Json File screenshot enter image description here For example, something like this code component.ts file.

import { Component } from '@angular/core';
import { ReleaseAction } from 'src/app/actions/release.action';
import { RELEASE_INIT_STATE } from '../../../../utils/constants/release_setup.constant';
import { ReduxStore } from 'src/app/store/Redux.store';
import { Router } from '@angular/router';
import * as _ from 'lodash';

@Component({
  selector: 'add-release',
  templateUrl: './add-release.component.html',
  styleUrls: ['./add-release.component.scss'],
  viewProviders: [ReleaseAction],
})
export class AddReleaseComponent {
  ReduxStore;
  state;
  breadCrumbsList;
  release_setupDetailsLink = '/release_setup/details';
  releaseForm: any = RELEASE_INIT_STATE;
  constructor( private _releaseAction: ReleaseAction, public router: Router) {
      this.ReduxStore = ReduxStore.getReduxStore();
      this.breadCrumbsList = [{text: 'Release Setup' , id: this.release_setupDetailsLink}];
  }

  onReleaseFormSubmit(formValues) {

      this.ReduxStore.dispatch(this._releaseAction.addRelease(formValues));
  }

}

For example, something like this code spec file.

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { Component, NO_ERRORS_SCHEMA } from '@angular/core';
import { ReleaseAction } from 'src/app/actions/release.action';
import { Router } from '@angular/router';
import { RELEASE_INIT_STATE } from '../../../../utils/constants/release_setup.constant';
import { _ } from 'lodash';
import { AddReleaseComponent } from './add-release.component';
import { ReduxStore } from 'src/app/store/Redux.store';
import configureStore from 'redux-mock-store' //ES6 modules
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

const middlewares = []
const mockStore = configureStore(middlewares)

describe('AddReleaseComponent', () => {
  let component: AddReleaseComponent;
  let fixture: ComponentFixture<AddReleaseComponent>;
  const initialState = {};  
  let ReduxStore;
  beforeEach(() => {
    ReduxStore = mockStore(initialState);
    spyOn(ReduxStore, "getReduxStore").and.returnValue(ReduxStore);
    const releaseActionStub = { addRelease: formValues => ({type: "TRIGGER_LAST_RELEASE"}) };
    const routerStub = { navigateByUrl: release_setupDetailsLink => ({}) };
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule, ReactiveFormsModule, FormsModule],
      schemas: [NO_ERRORS_SCHEMA],
      declarations: [AddReleaseComponent]
      ,providers: [
        { provide: Router, useValue: routerStub }
      ]
    })

    TestBed.overrideProvider(ReleaseAction, { useValue: releaseActionStub });
    TestBed.overrideProvider(Router, { useValue: routerStub });
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(AddReleaseComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });
  it('can load instance', () => {
    console.log("add-release");
    expect(component).toBeTruthy();
  });

  describe('onReleaseFormSubmit', () =>{
    it('addRelease and url called properly', () => {
      let releaseForm = component.releaseForm;
      component.onReleaseFormSubmit(component.releaseForm);
      expect(component.ReduxStore.getActions()).toContain({type:"TRIGGER_LAST_RELEASE"})
      
    });
  });


});

All code same working fine in angular7 but not working in angular13. Could you explain me how to use it properly? Or have you an other method to do that?

It just doesn't feel right that I would have to do so when the only thing I need to change is the provider, i'm unsure what overrideProvider even does at this point! Any help would be greatly appreciated!

CodePudding user response:

viewProviders is a tricky topic, especially to override and restore them.

you can use ng-mocks. It will take care how to mock it and how to restore it:

beforeEach(() => {
  return MockBuilder(
    [
      // things to test
      AddReleaseComponent,

      // additional imports
      HttpClientTestingModule,
      ReactiveFormsModule,
      FormsModule,
    ],

    // its module to mock dependencies
    AddReleaseModule,
  )

  // customizing the mock of the viewProvider dependency
  .mock(ReleaseAction, {
    addRelease: formValues => ({type: "TRIGGER_LAST_RELEASE"}),
  })

  // providing Router
  .provide(
    MockProvider(
      Router,
      {navigateByUrl: release_setupDetailsLink => ({})}
    ),
  );
});

it('test', () => {
  const fixture = TestBed.createComponent(AddReleaseComponent);
  // ReleaseAction is its mock.
});

You can do that with other providers too: root providers, module providers, etc.

  • Related