【问题标题】:Angular 9 Unit Testing ngOnInit with a setTimeOut inside service带有 setTimeOut 内部服务的 Angular 9 单元测试 ngOnInit
【发布时间】:2020-05-04 05:50:23
【问题描述】:

我在服务中有一个带有 setTimeOut 函数的组件。要为此编写单元测试用例,我使用 tick 和 fakeAsync 来设置 TimeOut。但是,它没有被执行。即使我对如何在 if 条件下为 window['MyAirtelAppReact'] 编写测试用例感到好奇。

我已经尝试使用 flushMicrotasks 将清除当前队列中的所有微任务,但不确定这是否是这样做的方法? 我将如何编写单元测试来测试这个?

组件代码:


constructor(
    private dataService: DataService,
    private loadinSrvc: LoadingService,
    private router: Router,
    private toastr: ToastrService,
    public dialog: MatDialog
  ){
  if (window['MyAirtelAppReact'] !== undefined) {
    if (
      window['MyAirtelAppReact'] &&
      window['MyAirtelAppReact'].getParameters
    ) {
      const deviceInfoString = window['MyAirtelAppReact'].getParameters();
      const deviceInfo = JSON.parse(deviceInfoString);
      this.dataService.setAppDetails(deviceInfo);
    }
  } else if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
    window['webkit'].messageHandlers.getParameters.postMessage('');
  } else {
    const deviceInfo = {
      channel: 'web',
      deviceId: GLOBAL_PROPERTIES.DEVICE_ID,
    };
    this.dataService.setAppDetails(deviceInfo);
  }

  this.loadinSrvc.userChangeEvent.subscribe((user) =>
    setTimeout(() => {
      this.showLoader = {
        text: this.loadinSrvc.getLoaderText() || 'Please wait...',
        isLoader: user,
      };
    })
  );

  this.router.events.subscribe((event: Event) => {
    if (event instanceof NavigationEnd) {
      this.loadinSrvc.setLoader(false);
    }
    if (event instanceof NavigationStart) {
      this.loadinSrvc.setLoader(true);
    }
    if (event instanceof NavigationError) {
      this.toastr.error('Something went wrong, please retry.');
      this.loadinSrvc.setLoader(false);
    }
  });
}

规格文件:

describe('AppComponent', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        ReactiveFormsModule,
        RouterTestingModule,
        CommonModule,
        HttpClientModule,
        ToastrModule.forRoot({
          timeOut: 3000,
          positionClass: 'toast-bottom-right',
          maxOpened: 1,
          preventDuplicates: true,
        }),
        MatDialogModule,
      ],
      declarations: [AppComponent],
      providers: [
        CommonService,
        { provide: DataService, useClass: MockDataService },
      ],
    }).compileComponents();
  }));

  // try2
  it('should test some asynchronous code', fakeAsync(() => {
    const fixture = TestBed.createComponent(AppComponent);
    const component = fixture.componentInstance;
    fixture.detectChanges();
    component.showLoader = { isLoader: false, text: 'Please wait...' };

    const testObservable = from(Promise.resolve(true));
    let flag = false;

    testObservable.subscribe((result) => {
      flag = true;
    });

    flushMicrotasks();
    expect(flag).toBe(true); // PASSES
  }));
});

【问题讨论】:

    标签: angular unit-testing angular6 karma-jasmine angular9


    【解决方案1】:

    以下是在setTimeout 函数中评估 MyAirtelAppReact 案例和 showLoader 的简单测试(我放了一些 cmets,但请随时提问):

    import SpyObj = jasmine.SpyObj;
    import createSpy = jasmine.createSpy;
    import spyOn = jasmine.spyOn;
    import createSpyObj = jasmine.createSpyObj; 
    describe('test set', () => {
      let component: AppComponent;
      let fixture: ComponentFixture<AppComponent>;
      let dataServiceSpy: SpyObj<DataService>;
      let toastrServiceSpy: SpyObj<ToastrService>;
      let matDialogSpy: SpyObj<MatDialog>;
      const loadingServiceMock = {userChangeEvent: {subscribe: createSpy()}, getLoaderText: createSpy()};
      const routerMock = {events: {subscribe: () => null}};
    
      beforeEach(async(() => {
        dataServiceSpy = createSpyObj('DataService', ['setAppDetails']);
        toastrServiceSpy = createSpyObj('ToastrService', ['error']);
        matDialogSpy = createSpyObj('MatDialog', ['']);
    
        TestBed.configureTestingModule({
          declarations: [AppComponent],
          providers: [
            {provide: DataService, useValue: dataServiceSpy},
            {provide: LoadingService, useValue: loadingServiceMock},
            {provide: Router, useValue: routerMock},
            {provide: ToastrService, useValue: toastrServiceSpy},
            {provide: MatDialog, useValue: matDialogSpy},
          ]
        }).compileComponents();
      }));
    
      // Had to move "beforeEach" function body here as your code execute in component class constructor
      function setUp() {
        fixture = TestBed.createComponent(AppComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
      }
    
      it('test 1', fakeAsync(() => {
        // Won't create Observable and only spy upon "Observable" methods that are being used
        loadingServiceMock.userChangeEvent.subscribe.and.callFake(cb => cb({name: 'Some Fake User Data'}));
        // Here is null but can be anything else - eg. in other tests
        loadingServiceMock.getLoaderText.and.returnValue(null);
        // Won't run built in method but can be worth to check what was passed in and out
        spyOn(JSON, 'parse');
        // Create spy for further checks and it results to evaluate true in "if" check
        window['MyAirtelAppReact'] = {getParameters: createSpy()};
    
        setUp();
    
        expect(JSON.parse).toHaveBeenCalled(); // check for MyAirtelAppReact
        expect(dataServiceSpy.setAppDetails).toHaveBeenCalled(); // check for MyAirtelAppReact
    
        tick(); // For setTimeout
    
        expect(component.showLoader).toEqual({
          text: 'Please wait...',
          isLoader: {name: 'Some Fake User Data'}
        });
      }));
    });
    

    【讨论】:

    • 我遇到了一些错误 - 1. 找不到名称'SpyObj'。 2. 找不到名称'createSpy'。 3. 找不到名称“createSpyObj”。
    • 我将导入添加到答案中。在你认为合适的时候使用它们@rohityadav
    • 是的,谢谢,我已经添加了这些导入。
    • @rohityadav 我刚刚在本地运行它,这些地方都被覆盖了。也许你错过了什么?
    • @Buczkowski 你能帮我解决这个问题吗? stackoverflow-61591363
    猜你喜欢
    • 2019-06-17
    • 2020-08-08
    • 1970-01-01
    • 1970-01-01
    • 2017-11-27
    • 2021-10-27
    • 2021-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多