Error on async tests: Cannot use setInterval from within an async zone test

1 view
Skip to first unread message

mende...@gmail.com

unread,
Jul 25, 2016, 5:35:12 PM7/25/16
to Angular2
Cross posted to http://stackoverflow.com/questions/38574837/running-angular2-tests-that-call-settimeout-errors-with-cannot-use-setinterval

I'm upgrading rc4 from rc1 and my unit tests started having this problem (they were working before the upgrade):

> Cannot use setInterval from within an async zone test

My test is trying to make sure that a loading indicator is displayed while data is being fetched. Here's a simplified version that exposes the problem

import { inject, async, TestComponentBuilder, ComponentFixture} from '@angular/core/testing';
import {Http, Headers, RequestOptions, Response, HTTP_PROVIDERS} from '@angular/http';
import {provide, Component} from '@angular/core';

import {Observable} from "rxjs/Rx";

class MyService {
constructor(private _http: Http) {}
getData() {
return this._http.get('/some/rule').map(resp => resp.text());
}
}

@Component({
template: `<div>
<div class="loader" *ngIf="_isLoading">Loading</div>
<div class="data" *ngIf="_data">{{_data}}</div>
</div>`
})
class FakeComponent {
private _isLoading: boolean = false;
private _data: string = '';

constructor(private _service: MyService) {}

ngOnInit() {
this._isLoading = true;
this._service.getData().subscribe(data => {
this._isLoading = false;
this._data = data;
});
}
}

describe('FakeComponent', () => {
var service = new MyService(null);
var _fixture:ComponentFixture<FakeComponent>;

beforeEach(async(inject([TestComponentBuilder], (tcb:TestComponentBuilder) => {
return tcb
.overrideProviders(FakeComponent, [
HTTP_PROVIDERS,
provide(MyService, {useValue: service}),
])
.createAsync(FakeComponent)
.then((fixture:ComponentFixture<FakeComponent>) => {
_fixture = fixture;
});
})));

it('shows loading indicator while fetching data', (cb) => {
// Make the call to getData take one ms so we can verify its state while the request is pending
spyOn(service, 'getData').and.returnValue(Observable.of('value').delay(1));

_fixture.detectChanges();
expect(_fixture.nativeElement.querySelector('.loader')).toBeTruthy();
// Wait a few ms, should not be loading
setTimeout(() => {
_fixture.detectChanges();
expect(_fixture.nativeElement.querySelector('.loader')).toBeFalsy();
cb();
}, 10);
});
});


It's interesting that the following test doesn't have any errors

it('lets you run timeouts', async(() => {
setTimeout(() => {
expect(1).toBe(1);
}, 10);
}));


Any suggestions? How do other people deal with testing code that runs asynchronously?

Reply all
Reply to author
Forward
0 new messages