测试Angular可观察对象是否发出值或序列

时间:2018-12-18 13:37:47

标签: javascript angular jasmine rxjs 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());
    }));
});

上面的方法可以测试期望值,但是仅在服务实际发出值时才起作用。如果遇到服务无法发送值的极端情况,则测试本身实际上会通过,Jasmine会记录警告消息“应该创建SPEC HAS NO EXPECTATIONS”。

我在Google上搜索了一段时间,试图弄清楚如何将此案视为错误,并提出了这种方法。

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

以上内容仅适用于 synchronous 可观察对象,并且对我来说感觉像代码。另一位开发人员会看到这一点,并认为这是质量较差的测试。

所以考虑了几天之后。我想到了使用takeUntil()来强制可观察对象完成然后测试预期的结果。

例如:

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);
    }));
});

在上面的示例中,该值存储在局部变量中,然后在可观察对象完成时检查预期结果。我通过将afterEach()takeUntil()一起使用来强制完成操作。

问题:

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

1 个答案:

答案 0 :(得分:3)

在我看来这太过分了。

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

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

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