Angular Unit Testing - Verify emitted value from an observable using marble testing

ⅰ亾dé卋堺 提交于 2020-04-18 03:45:23

问题


I'm creating some unit tests for an Angular application that I have. I have managed to test services that make HTTP calls without any problems. I now moved to a different kind of service, which is shown below.

Code

import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';

import { UICoupon } from '../models';

@Injectable()
export class ClaimCouponService {
    hasClaimedCoupons = false;

    claimedCoupons: UICoupon[] = [];

    onClaimCoupons: Observable<UICoupon[]>;

    private couponsUpdate: Subject<UICoupon[]> = new Subject<UICoupon[]>();

    constructor() {
        this.onClaimCoupons = this.couponsUpdate.asObservable();
    }

    claimCoupon(coupon: UICoupon) {
        if (!coupon.claimed) {
            coupon.claimed = true;
            this.claimedCoupons.push(coupon);
        }
        this.hasClaimedCoupons = true;
        this.couponsUpdate.next(this.claimedCoupons);
    }
}

I have managed to test the logic for this service using the "Subscribe / Assert pattern". Using the below code:

...

it('should claim a coupon', (done) => {
    claimCouponsService.onClaimCoupons
        .subscribe(claimedCoupons => {
            expect(claimedCoupons).toEqual([mockData[0]]);
            done();
        });

    claimCouponsService.claimCoupon(mockData[0]);
});

The above works well, however I was researching and I was curious about Marble Testing. I've read a few articles and I like how the logic is structured in the test. I've tried to replicate the above test with Marble Testing, but in my case I couldn't find a way to verify what is emitted from the service after the claimCoupon(...) function is run.

let scheduler: TestScheduler;
let claimCouponsService: ClaimCouponsService;

...

it('should claim a coupon', (done) => {
    const expectedObservable = claimCouponsService.onClaimCoupons;

    scheduler.run(runHelpers => {
        claimCouponsService.claimCoupon(mockData[0]);

        const expectedMarble = '^a|';
        const expectedData = { a: [mockData[0]] };

        runHelpers.expectObservable(expectedObservable)
            .toBe(expectedMarble, expectedData);
    });
});

I'm pretty sure that this is possible, but I have some kind of mistake in my test - or haven't really understood the way marble testing works. The above results in an error Expected $.length = 0 to equal 1. which I think means that the observable didn't get any values. I know the test I wrote does run successfully, however I'm curious to see how Marble Testing can be used.

来源:https://stackoverflow.com/questions/60817058/angular-unit-testing-verify-emitted-value-from-an-observable-using-marble-test

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!