gpt4 book ai didi

angular - Marble 测试 rxjs 在 Angular 服务上可观察到

转载 作者:行者123 更新时间:2023-12-04 17:20:58 26 4
gpt4 key购买 nike

我有一个带有公开 observable 的 Angular 服务,我正在尝试使用 rxjs TestScheduler 进行大理石测试。服务上的方法使用 BehaviorSubject 作为源来控制 observable 发出的值。这是一个非常简单的例子:

import { Injectable } from "@angular/core";
import { Observable } from "rxjs";
import { BehaviorSubject } from "rxjs";

@Injectable()
export class MyService {
private _isVisibleSubject: BehaviorSubject<boolean> = new BehaviorSubject<
boolean
>(true);

isVisible$: Observable<boolean> = this._isVisibleSubject.asObservable();

constructor() {}

toggleVisibility() {
this._isVisibleSubject.next(!this._isVisibleSubject.value);
}
}
MyService 的简单单元测试。我想测试两个条件:
  • isVisible$ observable 以 true
  • 开头
  • 当 toggleVisibility 被调用两次时,isVisible$ 有 3 个值,true、false 和返回 true

  • 这是测试类
    import { TestBed } from '@angular/core/testing';
    import { TestScheduler } from 'rxjs/testing';

    import { MyService } from './my.service';

    describe('MyService ', () => {

    let service: MyService ;
    const testScheduler: TestScheduler = new TestScheduler((actual, expected) => {
    expect(actual).toEqual(expected);
    });

    beforeEach(() => {
    TestBed.configureTestingModule({ providers: [MyService] });
    service = TestBed.inject(MyService);
    });

    it('Should start out visible', () => {

    // This one is easy enough, it starts out visible and nothing else happens

    testScheduler.run((helpers) => {

    const { expectObservable } = helpers;

    const values: {[key: string]: boolean} = {'a': true};
    const expected = 'a';

    expectObservable(service.isVisible$).toBe(expected, values);
    });


    it('Should toggle visibility back and forth', () => {

    testScheduler.run((helpers) => {

    const { expectObservable } = helpers;

    const values: {[key: string]: boolean} = {'a': true, 'b': false};
    const expected = 'aba'; // I've also tried with various frames between, eg '-a-b-a'

    service.toggleVisibility();
    service.toggleVisibility();

    expectObservable(service.isVisible$).toBe(expected, values);
    });
    });
    当我运行它时,第一个测试通过,但第二个测试失败,并出现类似 Expected $.length = 1 to equal 3. 的错误我已经通过运行如下测试来验证该值是否实际发生了变化:
        testScheduler.run((helpers) => {

    const { expectObservable } = helpers;

    const values: {[key: string]: boolean} = {'b': false};
    const expected = 'b';

    service.toggleVisibility();

    expectObservable(service.isVisible$).toBe(expected, values);
    });
    我假设问题是 service.isVisible$ 在调用 expectObservable() 之前不会订阅,因此以前的值丢失了。我翻阅了 rxjs documentation on marble testing但无法弄清楚这一点。
    我意识到我可以在测试开始时手动设置对 isVisible$ observable 的订阅,并在我进行更改时验证状态,但这并不像使用弹珠测试那样好。
    我想做的可能吗?

    最佳答案

    这是一个非常有趣的问题,我将分享我的观点,为什么它不起作用。
    因此,当到达这些行时:

    service.toggleVisibility();
    service.toggleVisibility();
    service.isVisible$ observable 尚未订阅。更具体地说, BehaviorSubject它源自没有订阅者。
    然后,当线
    expectObservable(service.isVisible$).toBe(expected, values);
    到达后, BehaviorSubject终于有了它的第一个订阅者并将发出正确的值。测试未通过,因为您期望发出 3 个值,但实际上只有一个。
    解决这个问题的一种方法可能是:
     it('Should toggle visibility back and forth', () => {
    testScheduler.run((helpers) => {

    const { expectObservable } = helpers;

    const values: {[key: string]: boolean} = {'a': true, 'b': false};
    const expected = 'aba';

    const src$ = merge(
    // the other `source` which defines the changes in time
    of(...expected).pipe(
    // only 2 toggle operations are needed
    // because `service.isVisible$` starts with `true`
    take(2),

    tap(v => service.toggleVisibility())

    // with this, `.next()` notifications will be ignored
    // which is what we want, because we only subscribed to this in order to
    // simulate changes that occur in time
    ignoreElements(),
    )

    // the observable whose values we want to examine
    service.isVisible$,
    )

    expectObservable(src$).toBe(expected, values);
    });
    })
    请注意,如果您想要更复杂的时间范围,例如 a---b---a---10s--c ,您可以替换 of(...)cold(timePattern, values) .

    关于angular - Marble 测试 rxjs 在 Angular 服务上可观察到,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66251354/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com