本文介绍了使用打字稿,业力和茉莉花进行单元测试RxJS Observable.timer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Angular2,Karma和Jasmine的新手.目前我正在使用Angular 2 RC4 Jasmine 2.4.x我有一个Angular 2服务,它会定期像这样调用http服务:

Hi I'm relatively new to Angular2, Karma and Jasmine. Currently I'm using Angular 2 RC4 Jasmine 2.4.xI have an Angular 2 service which periodically calls an http service like this:

getDataFromDb() { return Observable.timer(0, 2000).flatMap(() => {
        return this.http.get(this.backendUrl)
            .map(this.extractData)
            .catch(this.handleError);
    });
}

现在,我要测试功能.出于测试目的,我通过执行以下操作在没有Observable.timer的单独函数上测试了"http.get":

Now I want to test the functionality. For testing purposes I have just tested the "http.get" on a separate function without the Observable.timer by doing:

const mockHttpProvider = {
    deps: [MockBackend, BaseRequestOptions],
    useFactory: (backend: MockBackend, defaultOptions: BaseRequestOptions) => {
        return new Http(backend, defaultOptions);
    }
}

describe('data.service test suite', () => {
    var dataFromDbExpected: any;

    beforeEachProviders(() => {
        return [
            DataService,
            MockBackend,
            BaseRequestOptions,
            provide(Http, mockHttpProvider),
        ];
    });

    it('http call to obtain data',
        inject(
            [DataService, MockBackend],
            fakeAsync((service: DataService, backend: MockBackend) => {
                backend.connections.subscribe((connection: MockConnection) => {
                    dataFromDbExpected =  'myData';
                    let mockResponseBody: any = 'myData';
                    let response = new ResponseOptions({ body: mockResponseBody });
                    connection.mockRespond(new Response(response));

                });
                const parsedData$ = service.getDataFromDb()
                    .subscribe(response => {
                        console.log(response);
                        expect(response).toEqual(dataFromDbExpected);
                    });
            })));
});

我显然想使用Observable.timer测试整个功能.我认为可能要使用rxjs框架中的TestScheduler,但是我怎样才能告诉我只将Timer函数重复x次呢?我在打字稿上下文中找不到任何使用它的文档.

I obviously want to test the whole function with the Observable.timer. I think one might want to use the TestScheduler from the rxjs framework, but how can I tell to only repeat the timer function for x times? I couln't find any documentation using it in the typescript context.

我正在使用rxjs 5 beta 6

I'm using rxjs 5 beta 6

添加了Angular 2.0.0最终版本的工作示例:

Added working example for Angular 2.0.0 final release:

describe('when getData', () => {
    let backend: MockBackend;
    let service: MyService;
    let fakeData: MyData[];
    let response: Response;
    let scheduler: TestScheduler;

    beforeEach(inject([Http, XHRBackend], (http: Http, be: MockBackend) => {
        backend = be;
        service = new MyService(http);
        fakeData = [{myfake: 'data'}];
        let options = new ResponseOptions({ status: 200, body: fakeData });
        response = new Response(options);

        scheduler = new TestScheduler((a, b) => expect(a).toEqual(b));
        const originalTimer = Observable.timer;
        spyOn(Observable, 'timer').and.callFake(function (initialDelay, dueTime) {
            return originalTimer.call(this, initialDelay, dueTime, scheduler);
        });
    }));
    it('Should do myTest', async(inject([], () => {
        backend.connections.subscribe((c: MockConnection) => c.mockRespond(response));
        scheduler.schedule(() => {
            service.getMyData().subscribe(
                myData => {
                    expect(myData.length).toBe(3,
                        'should have expected ...');
                });
        }, 2000, null);
        scheduler.flush();
    })));
});

推荐答案

您需要将TestScheduler注入到beforeEach部分内部的timer方法中:

You need to inject the TestScheduler into the timer method inside a beforeEach part:

beforeEach(function() {
  this.scheduler = new TestScheduler();
  this.scheduler.maxFrames = 5000; // Define the max timespan of the scheduler
  const originalTimer = Observable.timer;
  spyOn(Observable, 'timer').and.callFake(function(initialDelay, dueTime) {
    return originalTimer.call(this, initialDelay, dueTime, this.scheduler);
  });
});

之后,您完全可以使用scheduleAbsolute来控制时间:

After that you have full control of the time with scheduleAbsolute:

this.scheduler.schedule(() => {
  // should have been called once
  // You can put your test code here
}, 1999, null);

this.scheduler.schedule(() => {
  // should have been called twice
  // You can put your test code here
}, 2000, null);

this.scheduler.schedule(() => {
  // should have been called three times
  // You can put your test code here
}, 4000, null);

this.scheduler.flush();

您需要scheduler.flush()来启动TestScheduler.

You need scheduler.flush() to start the TestScheduler.

因此,如果您只想测试X次,则可以根据需要频繁使用计划功能(以及正确的绝对时间(以毫秒为单位)).

edit: so if you want to only test it X times, use the schedule functions as often (and with the right absolute times in milliseconds) as you wish.

edit2:我添加了缺少的调度程序开始

edit2: I added the missing scheduler start

edit3:我更改了它,因此应该与RxJs5一起使用

edit3: I changed it so should be working with RxJs5

edit4:添加maxFrames设置,因为默认设置为750ms,这将阻止测试运行时间更长的序列.

edit4: Add maxFrames setting since the default is 750ms and will prevent testing longer-running sequences.

这篇关于使用打字稿,业力和茉莉花进行单元测试RxJS Observable.timer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-03 20:15