繁体   English   中英

使用SetTimeout时Angular 4测试失败

[英]Angular 4 test fails when SetTimeout is used

我写了一个非常简单的测试,它期望组件是真实的。 它正在工作,但是一旦我将SetTimeOut放在oninit中,它就会开始失败并显示以下内容。

错误:超时-jasmine.DEFAULT_TIMEOUT_INTERVAL指定的超时内未调用异步回调。

describe('AppComponent', () => {
  let appComponent: AppComponent;
  let fixture: ComponentFixture<AppComponent>;

  beforeEach(async(() => {
    var errorMessages = new Array<ErrorMessage>();
    errorMessages.push(new ErrorMessage(500));

    TestBed.configureTestingModule({
      declarations: [
        AppComponent
      ],
      imports: [
        RouterTestingModule,
        MessagesModule
      ],
      providers: [
        { provide: AuthService, useValue: TestHelper.createAuthServiceSpy() },
        { provide: ErrorHandlingService, useValue: TestHelper.createErrorHandlingServiceSpy(errorMessages) }
      ]
    }).compileComponents();

    fixture = TestBed.createComponent(AppComponent);
    appComponent = fixture.debugElement.componentInstance;
    fixture.detectChanges();
  }));

  it('should create the app', async(() => {
    expect(appComponent).toBeTruthy();
  }));

  it('should show error in case of failure', async(() => {
    expect(appComponent.errorMessage.length).toBe(1);
  }));

  it('should get username for loggedin user', async(() => {
    expect(appComponent.username).toBe("username");
  }));
});

他们所有的三个失败,当我评论SetTimeOut它开始通过。

export class AppComponent implements OnInit {
    username: string = "";
    errorMessage: Message[] = [];
    showError: boolean = false;
    private activatedRoute: ActivatedRoute;
    constructor(public authService: AuthService, private renderer: Renderer, private errorhandlingService: ErrorHandlingService, private router: Router, private titleService: Title) {
        localStorage.removeItem(AppConstants.authenticationLocalStorageKey);
    }

    ngOnInit(): void {
        this.router.events.subscribe(event => {
            if (event instanceof NavigationEnd) {
                var title = this.getTitle(this.router.routerState, this.router.routerState.root).join('-');
                this.titleService.setTitle(title);
            }
        });

        this.errorhandlingService.getErrors().subscribe(errorMessages => {
            let errorMessage: ErrorMessage = errorMessages.pop();
            this.errorMessage = errorMessage ? [{ severity: 'error', summary: `Error Code: ${errorMessage.statusCode}`, detail: `(${errorMessage.text})` }] : [];
            this.renderer.setElementProperty(document.body, "scrollTop", 0);
            this.showError = true;
            setTimeout(() => {
                this.showError = false;
            }, AppConstants.errorMessageFadeTime);
        });
        this.authService.getUsername().subscribe(data => this.username = data
            , error => this.errorhandlingService.handleError(error, 'could not get username'));
    }

    onDeactivate() {
        //scroll to top of page after routing
        this.renderer.setElementProperty(document.body, "scrollTop", 0);
    }

    private getTitle(state, parent) {
        var data = [];
        if (parent && parent.snapshot.data && parent.snapshot.data.title) {
            data.push(parent.snapshot.data.title);
        }

        if (state && parent) {
            data.push(... this.getTitle(state, state.firstChild(parent)));
        }
        return data;
    }


}

下面是html

<div>
        <div class="center-text">
            <div class="errorMessage" *ngIf="showError"><p-messages [value]="errorMessage"></p-messages></div>
            <router-outlet (deactivate)="onDeactivate()"></router-outlet>
        </div>
    </div>

我尝试了fakesync并完成了,但仍然出现相同的错误,有什么建议吗?

我建议您如下创建一个假类,

let errorOccured = false;

class FakeAuthService {
    getErrors(){
     return Observable.of(errorOccured);
    }
}

  providers: [
    { provide: AuthService, useClass: FakeAuthService},

  ]

TestBed beforeEach将其TestBed beforeEach

authService = TestBed.get(AuthService);

像之前一样声明一个变量beforeEach async

let authService : AuthService

更新1:

setTimeOut逻辑包含在订阅的完成事件中,如下所示:

this.errorhandlingService.getErrors().subscribe(errorMessages => {
    let errorMessage: ErrorMessage = errorMessages.pop();
    this.errorMessage = errorMessage ? [{ severity: 'error', summary: `Error Code: ${errorMessage.statusCode}`, detail: `(${errorMessage.text})` }] : [];
    this.renderer.setElementProperty(document.body, "scrollTop", 0);
    this.showError = true;

},error=>{},

()=>{
    setTimeout(() => {
        this.showError = false;
    }, AppConstants.errorMessageFadeTime);
});

假设代码的第二部分在您的实际服务中而不是测试中:

Angular提供的async回调外观并等待异步代码,例如ObservablesPromisessetTimeouts 它尝试在检查答案之前解决被测组件的方法调用。

Jasmine本身具有一个名为DEFAULT_TIMEOUT_INTERVAL的配置选项。 在异步测试中(仅使用jasmine,而不是Angular的测试工具),您可以将一个名为done()的方法传递到it块中,Jasmine将等待一定的时间间隔以调用该方法。 这是为了测试异步测试。 默认超时为5秒,因此,如果您调用的超时为5000,则由于setTimeout执行的恶作剧,Jasmine可能没有足够的时间进行检查。

Angular的async将Jasmine done()包装在一个不错的小调用中,它将在异步功能完成后执行测试。

无论哪种方式,你只需要使用async异步测试。 如果测试没有异步结果,请不要等待测试。

在您的情况下,您可以为异步测试设置一个beforeEach块,然后将assert包裹在大于5000的超时中,或者您可以仅针对那些测试更改jasmine配置:

... previous tests

describe('timeout tests', () => {

  beforeEach(() => {
    jasmine.DEFAULT_TIMEOUT_INTERVAL = 5250;
  });

  it('should display error for five seconds', async(() => {
     ...tests
  }));

});
... more tests

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM