首页 > 解决方案 > 测试用例单独运行时通过,但在组中运行时失败

问题描述

我有以下几个测试用例,它们在单独执行时运行成功,但在组运行时随机失败。他们都使用setTimeout. 它们位于单个文件中,以不同的方法spec隔离。describe

例如。这个测试用例(使用setTimeout)在我自己运行时通过,但是当我在组中运行时,它失败了。我怀疑这个问题与setTimeout. 我尝试使用done,但这并不能解决问题。

    describe('AppComponent Test suite', () => {

      let component: AppComponent;
      let fixture: ComponentFixture<AppComponent>;

      beforeEach(async(() => {
        TestBed.configureTestingModule({
          declarations: [
            AppComponent,
    ...
          ],
          imports: [
    ....
          ],
          providers: [{provide: APP_BASE_HREF, useValue: '/'},
....]

    }).compileComponents();
  }));


      beforeEach(() => {
        fixture = TestBed.createComponent(AppComponent);
        component = fixture.componentInstance;
        let componentDE = fixture.debugElement;
        let componentNE:HTMLElement = componentDE.nativeElement;
        componentNE.setAttribute("signup","someIncorrectValue");
        fixture.detectChanges();
      });
      it('should show dialog message if the application has unrecognised value of signup attribute in url',(done)=>{
        spyOn(component,'showDialog');
        setTimeout(()=>{
          expect(component.showDialog).toHaveBeenCalledWith("Unrecognised message: someIncorrectValue",jasmine.any);
        },1000); done();
      });
    });

想象在同一个文件中有更多类似的测试用例,每个测试用例describe都使用setTimeout.

他们为什么会失败?如果问题是同步,我如何同步它们?

更新

我也试过了asyncawait但没有快乐!

it('should show dialog message if the application has unrecognised value of signup attribute in url',async ()=>{
    spyOn(component,'showDialog');
    await setTimeout(()=>{
      expect(component.showDialog).toHaveBeenCalledWith("Unrecognised message: someIncorrectValue",jasmine.any);

      },1000);

  });

我还将调用移到了doneinsidesetTimeout的回调,但那里也没有任何乐趣。

it('should show dialog message if the application has unrecognised value of signup attribute in url', (done)=>{
    spyOn(component,'showDialog');
     setTimeout(()=>{
      expect(component.showDialog).toHaveBeenCalledWith("Unrecognised message: someIncorrectValue",jasmine.any);
      done();
      },1000);
  });

组件是应用程序的入口点,通过signupurl.

<app-root signup=@signup> 

注册会在启动时告诉 Angular 应用程序是否因为用户点击了注册链接而启动。因此,角度可以显示注册是否成功的消息。早些时候我遇到了以下问题(Getting ExpressionChangedAfterItHasBeenCheckedError 错误我从另一个组件更新组件的属性)并解决它,我在应用程序组件中添加setTimeoutngAfterViewInit一个

ngAfterViewInit(){


    setTimeout(()=>{
      this.checkIfSignupProcess();
      this.authGuard.authGuardError$.subscribe((authGuardContext:AuthGuardContext)=>{
        this.handleAuthGuardContextMessage(authGuardContext);
      });
      this.dialogService.dialogMessage$.subscribe((message:DialogServiceMessageContext)=>{
        console.log("received message from Dialog box service");
        this.handleDialogServiceMessage(message);
      })
    },100);

    /*
    OR
    this.isSignupProcess(); //this will cause ExpressionChangedAfterItHasBeenCheckedError error s the function changes message of DialogComponent but the change detection isn't complete.
    this.cd.detectChanges();
    */
  }

更新 2

我尝试使用 'tick' 但测试仍然失败,即使单独运行也是如此。

fit('should show dialog message if the application has unrecognised value of signup attribute in url', ()=>{
    jasmine.clock().install();
    spyOn(component,'showDialog');
    setTimeout(() => {
      console.log("in spec's timeout");
      expect(component.showDialog).toHaveBeenCalledWith("Unrecognised message: someIncorrectValue",jasmine.any);

    },1000);
    jasmine.clock().tick(1001);
    jasmine.clock().uninstall();
     /*setTimeout(()=>{
      expect(component.showDialog).toHaveBeenCalledWith("Unrecognised message: someIncorrectValue",jasmine.any);
      done();
      },1000);*/
  });

失败的原因是Expected spy showDialog to have been called with [ 'Unrecognised message: someIncorrectValue', Function ] but it was never called.

更新 3

我注意到,即使我的组件中的超时值为 100,而我的规范中的超时值为 1000,规范超时首先到期!!!

我的组件中应该显示对话框的代码在我的规范代码之后调用,即使组件中的超时值是 100,而规范中的超时值为 10000!

组件超时

setTimeout(()=>{
      console.log("timeout of component");
      this.checkIfSignupProcess();
    ...,100
}

规范的超时

fit('should show dialog message if the application has unrecognised value of signup attribute in url', ()=>{
    jasmine.clock().install();
    spyOn(component,'showDialog');
    setTimeout(() => {
      console.log("in spec's timeout 10000");
      expect(component.showDialog).toHaveBeenCalledWith("Unrecognised message: someIncorrectValue",jasmine.any);

    },10000);
    jasmine.clock().tick(10001);
    jasmine.clock().uninstall();
     /*setTimeout(()=>{
      expect(component.showDialog).toHaveBeenCalledWith("Unrecognised message: someIncorrectValue",jasmine.any);
      done();
      },1000);*/
  });

标签: jasmineangular6karma-jasmineangular-test

解决方案


不知道他们为什么会失败,但为了摆脱setTimeout,您可以尝试组合callThroughcallFake如下所示:

it('should show dialog ...', (done)=>{
    spyOn(component,'showDialog').and.callThrough().and.callFake(() => {
        expect(component.showDialog).toHaveBeenCalledWith("Unrecognised message: someIncorrectValue",jasmine.any);
        done();
    });
});

推荐阅读