angular2:如何测试具有可观察时间间隔的组件 [英] angular2: how to test a component which has an observable time interval

查看:104
本文介绍了angular2:如何测试具有可观察时间间隔的组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个幻灯片组件,其中包含一个滑动对象的Input数组,并显示每个幻灯片,只要它们在其slide.time中定义即可.还有两个按钮,单击它们必须滑到下一个项目并重置计时器.为了使这项工作有效,我正在使用类似这样的Observable:

I have a slide-show component that has an Input array of slide objects and shows each one as long as it's been defined in slide.time of itself. also there are two buttons that clicking them has to slide to the next item and reset the timer. in order to make this work, I'm using Observables like this:

/**
 * a "SUBJECT" for pausing(restarting) the slider's auto-slide on user's click on left and right arrows
 * @type {Subject}
 */
private pauser = new Subject();

/**
 * the main observable for timer (before adding the pause/reset option)
 * @type {Observable<T>}
 */
private source = Observable
    .interval(1000)
    .timeInterval()
    .map(function (x) { /*return x.value + ':' + x.interval;*/ return x })
    .share();

/**
 * the final timer, which can be paused
 * @type {Observable<R>}
 */
private pausableSource = this.pauser.switchMap(paused => paused ? Observable.never() : this.source);

/**
 * the subscription to the timer which is assigned at OnInit hook , and destroyed at OnDestroy
 */
private subscription;

ngOnInit(){
    this.subscription = this.pausableSource.subscribe(() => {
        //doing changes to the template and changing between slides
    });
    this.pauser.next(false);
}

ngOnDestroy() {
    this.subscription.unsubscribe();
}

,它可以正常工作. 现在要测试该组件,我在测试主机组件中提供一些数据,并想检查它的功能,如下所示:

and it's working properly. now to test this component, I'm giving it some data within a test-host component and want to check it's functionality like this:

it("should show the second (.slidingImg img) element after testHost.data[0].time seconds 
    have passed (which here, is 2 seconds)", () => {
    //testing
});

我尝试了在文档或互联网上任何地方找到的很多东西,但是它们都不适合我.问题是我无法以可观察的计时器执行下一个动作的方式来模拟时间的流逝,这就像没有时间过去一样.对我不起作用的两种方法是:

i tried many things that i found in docs or anywhere on the internet, but none of them work for me. the problem is that I can't mock the passage of time in a way that the observable timer would perform next actions, and it's like no time has passed whatsoever. two of the ways that haven't worked for me are these:

it("should show the second (.slidingImg img) element after testHost.data[0].time seconds 
    have passed (which here, is 2 seconds)", fakeAsync(() => {
    fixture.detectChanges();
    tick(2500);
    flushMicrotasks();
    fixture.detectChanges();
    let secondSlidingImg = fixture.debugElement.queryAll(By.css('.slidingImg'))[1].query(By.css('img'));
    expect(secondSlidingImg).toBeTruthy();
    //error: expected null to be truthy
}));

我是从angular2文档中得到的.

i got this from angular2 docs.

和:

beforeEach(() => {
    fixture = TestBed.createComponent(TestHostComponent);

    testHost = fixture.componentInstance;

    scheduler = new TestScheduler((a, b) => expect(a).toEqual(b));

    const originalTimer = Observable.interval;
    spyOn(Observable, 'interval').and.callFake(function(initialDelay, dueTime) {
        return originalTimer.call(this, initialDelay, dueTime, scheduler);
    });
    // or:
    // const originalTimer = Observable.timer;
    // spyOn(Observable, 'timer').and.callFake(function(initialDelay, dueTime) {
    //     return originalTimer.call(this, initialDelay, dueTime, scheduler);
    // });
    scheduler.maxFrames = 5000;

});
it("should show the second (.slidingImg img) element after testHost.data[0].time seconds 
    have passed (which here, is 2 seconds)", async(() => {
    scheduler.schedule(() => {
        fixture.detectChanges();
        let secondSlidingImg = fixture.debugElement.queryAll(By.css('.slidingImg'))[1].query(By.css('img'));
        expect(secondSlidingImg).toBeTruthy();
        //error: expected null to be truthy
    }, 2500, null);
    scheduler.flush();
}));

我从此问题获得了这种方法.

i got this approach from this question.

所以我迫切需要知道我应该如何精确地模拟单元测试中的时间流逝,以便该组件的可观察时间间隔真正触发...

so I desperately need to know how exactly should I simulate time passage in my unit test so that the component's observable time interval would really trigger...

版本:

angular: "2.4.5"
"rxjs": "5.0.1"
"jasmine": "~2.4.1"
"karma": "^1.3.0"
"typescript": "~2.0.10"
"webpack": "2.2.1"    

推荐答案

fakeAsync在某些情况下不适用于RxJ.您需要在RxJs中手动移动内部计时器.遵循这些原则:

fakeAsync doesn't work for some case with RxJs. You need to manually move internal timer in RxJs. Something along those lines:

import {async} from 'rxjs/internal/scheduler/async';
...

describe('faking internal RxJs scheduler', () => {
  let currentTime: number;

  beforeEach(() => {
    currentTime = 0;
    spyOn(async, 'now').and.callFake(() => currentTime);
  });

  it('testing RxJs delayed execution after 1000ms', fakeAsync(() => {
    // Do your stuff
    fixture.detectChanges();
    currentTime = 1000;
    tick(1000);
    discardPeriodicTasks();

    expect(...);
  }));
});

这篇关于angular2:如何测试具有可观察时间间隔的组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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