Angular 2 Observable测试错误:无法在异步区域测试中使用setInterval [英] Angular 2 Observable testing Error: Cannot use setInterval from within an async zone test

查看:233
本文介绍了Angular 2 Observable测试错误:无法在异步区域测试中使用setInterval的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试测试一个组件,该组件使用一个进行异步http调用的服务。该服务返回一个Observable,组件订阅。

I'm trying to test a component, which uses a service that makes async http calls. The service returns an Observable, which the component subscribes on.

服务代码段:

getRecentMachineTemperatures(_machine_Id): Observable<IDeviceReadings[]> {

    return this.http.get(TemperatureService.URL + _machine_Id)
      .map(response => { return response.json(); })
      .map((records: Array<any>) => {
        let result = new Array<IDeviceReadings>();
        if (records) {
          records.forEach((record) => {
            let device = new IDeviceReadings();
            device.device_id = record.device_id;

            if (record.d) {
              record.d.forEach((t) => {
                let temperature = new ITemperature();
                temperature.timestamp = t.timestamp;
                temperature.value = t.temperature;

                device.temperatures.push(temperature);
              });
            }

            result.push(device);
          });
        }
        return result;
      });
  }

组件代码段:

  ngOnInit() {
    this.getRecentTemperatures();
  }

  getRecentTemperatures() {
    this.temperatureService.getRecentMachineTemperatures(this.machine_id)
      .subscribe(
        res => {
          let device1 = res[0];
          this.deviceId = device1.device_id;
          this.initTemperatures(device1.temperatures);
          this.updateChart();
        },
        error => console.log(error));
  }

My Test设置依赖关系,监视服务'getRecentMachineTemperatures'并设置i返回一些存根数据。我一直在谷歌搜索测试这个的方法,从而导致3个不同的测试,试图测试同样的事情。每个给我一个不同的错误。

My Test sets up dependencies, spies on the service 'getRecentMachineTemperatures' and sets i to return some stub data. I've been googling around for ways to test this, thus resulting in 3 different test, trying to test the same thing. Each giving me a different error.

temperature.component.spec.ts:

temperature.component.spec.ts:

let machine_id = 1;
let comp:                 TemperatureComponent;
let fixture:              ComponentFixture<TemperatureComponent>;
let de:                   DebugElement;
let el:                   HTMLElement;
let temperatureService:   TemperatureService;
let stubDevices:          IDeviceReadings[];
let stubTemperatures:     ITemperature[];
let spyRecentTemps:       Function;

describe('Component: Temperature', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [TemperatureComponent],
      imports: [ ChartsModule ],
      providers: [
        MockBackend,
        BaseRequestOptions,
        { provide: Http,
          useFactory: (backend, defaultOptions) => {
            return new Http(backend, defaultOptions);
          },
          deps: [MockBackend, BaseRequestOptions]},
        TemperatureService
      ]
    });

    stubDevices = new Array<IDeviceReadings>();

    let stubDevice = new IDeviceReadings();
    stubDevice.device_id = 'stub device';
    stubDevice.temperatures = new Array<ITemperature>();

    let stubTemp = new ITemperature();
    stubTemp.timestamp = new Date().getTime();
    stubTemp.value = 10;

    stubDevice.temperatures.push(stubTemp);
    stubDevices.push(stubDevice);

    stubTemperatures = new Array<ITemperature>();

    let stubTemp2 = new ITemperature();
    stubTemp.timestamp = new Date().getTime() + 1;
    stubTemp.value = 11;

    stubTemperatures.push(stubTemp2);

    fixture = TestBed.createComponent(TemperatureComponent);
    comp = fixture.componentInstance;

    temperatureService = fixture.debugElement.injector.get(TemperatureService);

    spyRecentTemps = spyOn(temperatureService, 'getRecentMachineTemperatures')
      .and.returnValue(Observable.of(stubDevices).delay(1));

    //  get the "temperature-component" element by CSS selector (e.g., by class name)
    de = fixture.debugElement.query(By.css('.temperature-component'));
    el = de.nativeElement;
  });

  it('should show device readings after getRecentTemperatures subscribe (fakeAsync)', fakeAsync(() => {
    fixture.detectChanges();
    expect(spyRecentTemps.calls.any()).toBe(true, 'getRecentTemperatures called');

    tick(1000);
    fixture.detectChanges();
    expect(el.textContent).toContain(stubDevices[0].temperatures[0].timestamp);
    expect(el.textContent).toContain(stubDevices[0].temperatures[0].value);
  }));

  it('should show device readings after getRecentTemperatures subscribe (async)', async(() => {
      fixture.detectChanges();
      expect(spyRecentTemps.calls.any()).toBe(true, 'getRecentTemperatures called');

      fixture.whenStable().then(() => {
        fixture.detectChanges();
        expect(el.textContent).toContain(stubDevices[0].temperatures[0].timestamp);
        expect(el.textContent).toContain(stubDevices[0].temperatures[0].value);
      });
  }));

  it('should show device readings after getRecentTemperatures subscribe (async) (done)', (done) => {
    async(() => {
      fixture.detectChanges();
      expect(spyRecentTemps.calls.any()).toBe(true, 'getRecentTemperatures called');

      fixture.whenStable().then(() => {
        fixture.detectChanges();
        expect(el.textContent).toContain(stubDevices[0].temperatures[0].timestamp);
        expect(el.textContent).toContain(stubDevices[0].temperatures[0].value);
      }).then(done);
    });
  });
});

fakeAsync失败:'错误:1个计时器仍在队列中。'

fakeAsync fails with: 'Error: 1 timer(s) still in the queue.'

async失败并显示:'错误:无法在异步区域测试中使用setInterval。'

async fails with: 'Error: Cannot use setInterval from within an async zone test.'

异步(已完成)失败with:'错误:超时 - 在jasmine.DEFAULT_TIMEOUT_INTERVAL指定的超时时间内未调用异步回调。'

async (done) fails with: 'Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'

我将如何测试具有异步服务依赖性的组件?

How would I go about testing components with a async service dependency?

根据我的理解,它可能是使用Date()在Rx库中的AsyncScheduler。现在而不是伪造的时间( https://github.com/angular/angular/issues/10127 )。如果是这样,这已被修复?或者有人找到了解决方法?

From what I understand it might be something about the AsyncScheduler within the Rx library using Date().now instead of faked time (https://github.com/angular/angular/issues/10127). If so has this been fixed? Or anyone found a workaround?

我正在使用angular-cli:1.0.0-beta.16。节点:4.4.2。 npm:3.10.6。 webpack 2.1.0-beta.22。

I'm using angular-cli: 1.0.0-beta.16. node: 4.4.2. npm: 3.10.6. webpack 2.1.0-beta.22.

推荐答案

我有..

import 'rxjs/add/operator/timeout';

return this.http[method](url, emit, this.options)
    .timeout(Config.http.timeout, new Error('timeout'))

导致此错误的原因。我相信在引擎盖下RXJS .timeout正在调用setInterval。

Which was causing this error. I believe under the hood RXJS .timeout is calling setInterval.

我通过切换来解决这个问题...

I fixed this by switching ...

it('blah', async(() => {     

to

it('blah', (done) => {

这篇关于Angular 2 Observable测试错误:无法在异步区域测试中使用setInterval的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆