Unit testing that items get filtered out of Observable (Jasmine/RxJS)

北战南征 提交于 2021-02-05 05:30:07

问题


I'm doing unit testing with Jasmine/Karma against an Angular service. I'd like to confirm that my service properly filters items.

For example, if I have a service to get people over a certain age, it

  1. should return people over the minimum age (positive case)
  2. should NOT return people under a the minimum age (negative case)

It's #2 that I'm struggling to test.

The service:

    getPeople(minAge: number): Observable<string> {
        const source = Observable.from([
            { name: 'Joe', age: 30 },
            { name: 'Frank', age: 20 },
            { name: 'Ryan', age: 50 }
        ]);
        return source
            .filter(person => person.age >= minAge)
            .map(person => person.name);
    }

The Positive unit test

    it('should return people over 30', () => {
        const service = new MyService();
        const minAge = 30;
        service.getPeople(minAge).subscribe(people => {
            expect(people.length).toBeGreaterThan(0);
        });
    });

And the Negative unit test

it('should not return people over 55', () => {
        const service = new MyService();
        const minAge = 55;
        service.getPeople(minAge).subscribe(people => {
            expect(people.length).toBe(0); // WE NEVER GET HERE!
        });
    });

In the negative case, the Observable never returns anything, and rightly so. But, how do I write a unit test to confirm this?


回答1:


Your observable is a stream of values, you may do something like:

Positive:

let invoked = 0;
service.getPerson(30).subscribe(() => {
   invoked++;
})
expect(invoked).toEqual(2);

Negative:

let invoked = 0;
service.getPerson(55).subscribe(() => {
   invoked++;
})
expect(invoked).toEqual(0);



回答2:


Your first test is wrong. It tests that the length of each string being emitted is greater than 0. That shouldn't be what you test: the test would pass even if your code emitted 'Frank'. What you should test is that the emitted person names are 'Joe' and 'Ryan':

const result: Array<string> = [];
service.getPeople(minAge).subscribe(people => {
  result.push(people);
});
expect(result).toEqual(['Joe', 'Ryan']); 

Your second test isn't really necessary, since your first test checks that the filtering results the correct names, and doesn't return the incorrect ones. But if you really want to keep it, then you should fail the test if the subscribe callback is called, since it should not be called:

service.getPeople(minAge).subscribe(people => {
  fail('should not be called');
});


来源:https://stackoverflow.com/questions/48389737/unit-testing-that-items-get-filtered-out-of-observable-jasmine-rxjs

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