【问题标题】:How to override Provider in Angular 13 for angular testing Jasmine Karma?如何覆盖 Angular 13 中的 Provider 以进行角度测试 Jasmine Karma?
【发布时间】:2022-10-20 22:46:47
【问题描述】:

因此,我查看了许多与在线覆盖提供程序相关的问题,但没有成功。 在这段代码中显示,我已经在角度版本 7 中工作,这个测试用例工作正常。当我升级到角度版本 13 时,测试用例失败并出现这样的错误。当组件中的代码注释比所有测试用例成功时,此错误与 overrideProviders 相关,否则失败。我必须用不同的模拟多次创建相同的服务。

错误:操作必须是普通对象。使用自定义中间件进行异步操作。

这是包Json文件截图 例如,像这样的代码 component.ts 文件。

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));
  }

}

例如,类似于此代码规范文件的内容。

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"})
      
    });
  });


});

所有代码在 Angular 7 中都可以正常工作,但在 Angular 13 中不能正常工作。你能解释一下如何正确使用它吗?还是您有其他方法可以做到这一点?

当我唯一需要更改的是提供者时,我不得不这样做是不对的,我不确定此时 overrideProvider 甚至会做什么!任何帮助将不胜感激!

【问题讨论】:

    标签: angular unit-testing jasmine karma-jasmine angular13


    【解决方案1】:

    viewProviders 是一个棘手的话题,尤其是覆盖和恢复它们。

    你可以使用ng-mocks。它将注意如何模拟它以及如何恢复它:

    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.
    });
    

    您也可以对其他提供者进行此操作:根提供者、模块提供者等。

    【讨论】:

    • 我已经在 viewProviders 操作方法中使用了 redux-mock-store 重写不起作用。
    • 您可以添加mockStorespyOn,它们不会影响模拟viewProviders 的行为。
    • gmeet 很好,给我一个链接。
    • 非常感谢您与我们分享您的经验。我们希望很快再见到你。” “我们非常感谢您抽出宝贵时间与我们分享您的评分。我们期待很快再次见到您
    • 你非常受欢迎。如果有帮助,你能接受答案吗?
    【解决方案2】:

    配置类型没有意义。 为什么在TestBed 中有一个提供程序部分,然后在它下面单独覆盖提供程序?

    TestBed.configureTestingModule({
      providers: [
        { provide: Router, useValue: routerStub },
        // this makes more sense for the scenario described above
        { ReleaseAction, useValue: releaseActionStub },
        { Router, useValue: routerStub },
      ]
    })
    
    // Why do this here separately?
    // TestBed.overrideProvider(ReleaseAction, { useValue: releaseActionStub });
    // TestBed.overrideProvider(Router, { useValue: routerStub });
    

    但是,如果由于某种原因您需要为不同的测试/场景覆盖提供者,那么你仍然需要定义它在主要providers: []然后覆盖它

    如果你考虑一下,那是有道理的。首先,您指定初始提供者,然后覆盖它。

    TestBed.configureTestingModule({
      providers: [
        { provide: Router, useValue: routerStub },
        // define the initial value
        { ReleaseAction, useValue: releaseActionStub },
        { Router, useValue: routerStub },
      ]
    })
    
    // in a beforeEach() or it()
    // override the initial value
    TestBed.overrideProvider(ReleaseAction, { useValue: releaseActionStubOverride });
    TestBed.overrideProvider(Router, { useValue: routerStubOverride });
    

    请注意,一旦“编译”TestBed,您将无法覆盖

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-07
      • 1970-01-01
      • 2020-05-12
      • 2020-06-02
      • 2017-06-10
      • 2015-12-07
      • 1970-01-01
      • 2019-03-26
      相关资源
      最近更新 更多