测试 Angular observable 是否发出值或序列

Rea*_*lar 3 javascript observable jasmine rxjs angular

我有一个服务,它创建一个发出值的 observable,测试发出的值是否符合预期相对容易。

例如:

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

    it('should emit true', async(() => {
        const service = TestBed.get(MyService);
        service.values$.subscribe((value) => expect(value).toBeTruthy());
    }));
});
Run Code Online (Sandbox Code Playgroud)

以上用于测试预期值,但仅在服务实际发出值时才有效。如果您遇到服务无法发出值的边缘情况,那么测试本身实际上会通过,并且 Jasmine 会记录警告消息“应该创建 SPEC HAS NO EXPECATIONS”。

我在谷歌上搜索了一段时间,试图弄清楚如何将这种情况作为错误来捕捉,并提出了这种方法。

    it('should emit true', async(() => {
        const service = TestBed.get(MyService);
        let value;
        service.values$.subscribe((v) => value = v);
        expect(value).toBeTruthy();
    }));
Run Code Online (Sandbox Code Playgroud)

以上仅适用于同步observables,对我来说感觉就像代码气味。另一个开发人员会看到这一点,并认为这是一个质量很差的测试。

所以在想了几天之后。我想到了使用takeUntil()强制 observable 完成然后测试预期结果。

例如:

describe('service', () => {
    let finished: Subject<void>;

    beforeEach(() => {
        TestBed.configureTestingModule({providers: [MyService]});
        finished = new Subject();
    });

    afterEach(() => {
        finished.next();
        finished.complete();
    });

    it('should emit true', async(() => {
        const service = TestBed.get(MyService);
        let value;
        service.changes$
            .pipe(
                takeUntil(finished),
                finalize(() => expect(value).toBeTruthy())
            )
            .subscribe((v) => value = v);
    }));
});
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,值被存储在一个局部变量中,然后当 observable 完成时检查预期的结果。我通过使用afterEach()with强制完成takeUntil()

题:

我的方法是否有任何副作用,如果是这样,执行这些类型的测试的更多 Angular/Jasmine 方式是什么。我担心您不应该在afterEach()生命周期调用期间执行期望断言。

小智 5

这对我来说似乎太过分了。

Jasmine 在其测试中提供了回调,您可以简单地使用它吗?

it('should X', doneCallback => {
  myObs.subscribe(res => {
    expect(x).toBe(y);
    doneCallback();
  });
});
Run Code Online (Sandbox Code Playgroud)

如果未调用回调,则测试失败并出现超时异常(意味着在此失败后将不再运行测试)