【问题标题】:How can I use the TestScheduler with promises and delays?如何使用带有承诺和延迟的 TestScheduler?
【发布时间】:2015-09-16 07:48:58
【问题描述】:

我正在尝试让 Jasmine、promises 和 Rx.TestScheduler 一起玩得很好,但我遇到了一个我似乎无法解决的障碍。

我想要实现的是使用 RxJs 和 Jasmine 测试延迟的承诺。

我在此 JsFiddle 中创建了该问题的最小再现:https://jsfiddle.net/t9gsymu2/2/

这是该小提琴的完整 javascript 代码:

'use strict';

// fail if a test takes longer than 1 second
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;

describe('TestScheduler', function () {
    it('should work when combining the testscheduler and delay', function (done) {
        var scheduler = new Rx.TestScheduler();
        var people = Rx.Observable.just({
            name: 'Jeff'
        });
        var peopleWithTheirAge = people.flatMap(function (person) {
            return Rx.Observable.just({
                name: 'Jeff',
                age: 25
            });
        });
        var delayedPeopleWithTheirAge = peopleWithTheirAge.delay(2000, scheduler);
        delayedPeopleWithTheirAge.subscribe(function (person) {
            expect(person).toEqual({
                name: 'Jeff',
                age: 25
            });
            done();
        });
        scheduler.start();
    });

    it('should work when combining the testscheduler, delay AND a promise', function (done) {
        var scheduler = new Rx.TestScheduler();
        var people = Rx.Observable.just({
            name: 'Jeff'
        });
        var peopleWithTheirAge = people.flatMap(function (person) {
            return Promise.resolve({
                name: 'Jeff',
                age: 25
            });
        });
        var delayedPeopleWithTheirAge = peopleWithTheirAge.delay(2000, scheduler);
        delayedPeopleWithTheirAge.subscribe(function (person) {
            expect(person).toEqual({
                name: 'Jeff',
                age: 25
            });
            done();
        });
        scheduler.start();
    });
});

两个测试都与 T 相同,唯一的区别是第一个测试使用Rx.Observable.just,第二个测试使用Promise.resolve。 (我可以使用Rx.Observable.fromPromise 来确保实际创建了一个 Observable,但是 1. 我已经尝试过了 2. https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/promises.md 的文档明确指出 flatMap 支持 Promise 对象)

第一个测试立即成功。 Observable 使用可以模拟时间的 Rx.TestScheduler 延迟 2 秒。 scheduler.start() 方法会立即执行任何计划任务,而不是等待 2 秒。 Jasmine 支持在您的测试中使用“done”参数进行异步测试,这实际上只是您认为测试完成时需要调用的函数。

但是,第二次测试失败。我假设这与 Promises 是异步的有关,这会导致 TestScheduler 无法处理这些回调中发生的任何事情。

非常感谢您对此事的任何帮助!

【问题讨论】:

    标签: javascript asynchronous jasmine rxjs


    【解决方案1】:

    我最近很火,这是我在 SO 上发布问题后不久第二次找到答案。

    无论如何,解决方案是使用 RxJs 库中内置的 MockPromise。

    所以不要使用Promise.resolve(true),而是使用scheduler.createResolvedPromise(100, true)

    这是工作小提琴:https://jsfiddle.net/t9gsymu2/4/

    以及完整的代码:

    'use strict';
    
    // fail if a test takes longer than 1 second
    jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
    
    describe('TestScheduler', function () {
        it('should work when combining the testscheduler and delay', function (done) {
            var scheduler = new Rx.TestScheduler();
            var people = Rx.Observable.just({
                name: 'Jeff'
            });
            var peopleWithTheirAge = people.flatMap(function (person) {
                return Rx.Observable.just({
                    name: 'Jeff',
                    age: 25
                });
            });
            var delayedPeopleWithTheirAge = peopleWithTheirAge.delay(2000, scheduler);
            delayedPeopleWithTheirAge.subscribe(function (person) {
                expect(person).toEqual({
                    name: 'Jeff',
                    age: 25
                });
                done();
            });
            scheduler.start();
        });
    
        it('should work when combining the testscheduler, delay AND a promise', function (done) {
            var scheduler = new Rx.TestScheduler();
            var people = Rx.Observable.just({
                name: 'Jeff'
            });
            var peopleWithTheirAge = people.flatMap(function (person) {
                return scheduler.createResolvedPromise(100, {
                    name: 'Jeff',
                    age: 25
                });
            });
            var delayedPeopleWithTheirAge = peopleWithTheirAge.delay(2000, scheduler);
            delayedPeopleWithTheirAge.subscribe(function (person) {
                expect(person).toEqual({
                    name: 'Jeff',
                    age: 25
                });
                done();
            });
            scheduler.start();
        });
    });
    

    【讨论】:

    • 没错。另外,如果您将使用TestScheduler,则实际上不需要done。在start 返回后,所有的值都已处理完毕。此外,通常使用MockObserver 比在订阅块中显式进行比较更容易。
    • 再次感谢您提供更多信息!我从你身上学到了很多。你是 RxJs 的贡献者吗?
    • 没问题!是的,我是贡献者之一。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-16
    • 2015-03-08
    • 1970-01-01
    • 1970-01-01
    • 2015-03-27
    • 2023-03-21
    相关资源
    最近更新 更多