【问题标题】:Testing async pipeable operators in RxJS在 RxJS 中测试异步管道操作符
【发布时间】:2020-05-28 21:30:28
【问题描述】:

有时我们有函数,它使用延迟等异步运算符修改原始源代码。

假设我们有一些非常简单的东西:

// Old syntax
function modify(source) {
   return source.delay(1000);
}

我正在使用弹珠测试 RxJs,所以我的测试看起来像:

it("mock chain style call (modify function)", function() {
    var values = {
      a: "test",
      x: "test"
    }; 

    var source = hot(    "-a", values);
    var delayTime = time( "--|");
    var result = cold(   "---x", values);

    var originalDelay = Rx.Observable.prototype.delay;
    spyOn(Rx.Observable.prototype, "delay").and.callFake(function () { 
       return originalDelay.call(this, delayTime, jm.getTestScheduler()); 
    });

    expect(modify(source)).toBeObservable(result);
});

这与 rxjs 库中用于测试的几乎相同:https://github.com/ReactiveX/rxjs/blob/master/spec/operators/delay-spec.ts

但我们必须修补 Observable.delay 函数,因为我们无法直接访问它。 而且效果很好。

但我们决定开始使用 RxJs 中的可管道操作符。有什么想法如何测试这个功能:

// New syntax
function modify(source) {
   return source.pipe(Rx.operators.delay(1000));
}

看起来像?

JsBin demo

【问题讨论】:

    标签: rxjs5 jasmine2.0 jasmine-marbles


    【解决方案1】:

    UPD

    Time progression syntax 在 rxjs 6.0.0 版本中可用。 所以你的测试可能看起来像:

    it('generate the stream correctly', () => {
        testScheduler.run(helpers => {
            const { cold, expectObservable, expectSubscriptions } = helpers;
            const input = ' -a-b-c|';
            const expected = '-- 9ms a 9ms b 9ms (c|)';
            /*
            // Depending on your personal preferences you could also
            // use frame dashes to keep vertical aligment with the input
               const input = ' -a-b-c|';
               const expected = '------- 4ms a 9ms b 9ms (c|)';
            // or
               const expected = '-----------a 9ms b 9ms (c|)';
    
            */
    
            const result = cold(input).pipe(
                concatMap(d => of(d).pipe(
                    delay(10)
                ))
            );
    
            expectObservable(result).toBe(expected);
       });
    

    原答案

    终于找到了一些解决方法,不确定它是否适用于所有情况。

    所以这里是我们修改函数的文件:

    import { Observable } from "rxjs";
    import { delay } from "rxjs/operators";
    
    export function modify<T>(source: Observable<T>): Observable<T> {
        return source.pipe(delay(1000));
    }
    

    这里的主要思想是将所有操作符作为对象导入,并监视此对象的方法:

    import * as operators from "rxjs/operators";
    ... 
    spyOn(operators, "delay")
    

    这里的问题是我得到了错误:

    Error: <spyOn> : delay is not declared writable or has no setter
    

    为了避免这个错误,我只是更改了对象中的属性描述符:

    /** 
     * Changes property descriptor to make possible to use spyOn function for imported 
     *  modules.
     */
     function spyOnOperator(obj: any, prop: string): any {
        const oldProp: Function = obj[prop];
        Object.defineProperty(obj, prop, {
            configurable: true,
            enumerable: true,
            value: oldProp,
            writable: true
        });
    
       return spyOn(obj, prop);
    }
    

    所以我的规范文件现在看起来像:

    import { cold, getTestScheduler, hot, time } from "jasmine-marbles";
    import * as operators from "rxjs/operators";
    import { modify } from "./modify";
    
    describe("Test delay: ", () => {
        it("mock chain style call (modify function)", () => {
            const originalDelay: Function = operators.delay;
            const values: any = {
                a: "test",
                x: "test"
            };
    
            const source: TestHotObservable = hot("-a", values);
            const delayTime: number = time("--|");
            const result: TestColdObservable = cold("---x", values);
    
            spyOnOperator(operators, "delay").and.callFake(() => {
                return originalDelay.call(this, delayTime, getTestScheduler());
            });
    
            expect(modify(source)).toBeObservable(result);
        });
    });
    

    【讨论】:

    • 我收到TypeError: Cannot redefine property: delay
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多