admin管理员组文章数量:1402857
I have a service that creates an observable that emits values, and it's relatively easy to test that an emitted value is as expected.
For example:
describe('service', () => {
beforeEach(() => {
TestBed.configureTestingModule({providers: [MyService]});
});
it('should emit true', async(() => {
const service = TestBed.get(MyService);
service.values$.subscribe((value) => expect(value).toBeTruthy());
}));
});
The above works to test the expected value, but it only works if the service actually emits a value. If you have the edge case where the service fails to emit a value, then the test itself actually passes and Jasmine logs the warning message "SPEC HAS NO EXPECTATIONS should be created".
I searched Google for a while trying to figure out how to catch this case as an error and came up with this approach.
it('should emit true', async(() => {
const service = TestBed.get(MyService);
let value;
service.values$.subscribe((v) => value = v);
expect(value).toBeTruthy();
}));
The above works only for synchronous observables and feels like code smell to me. Another developer will see this and think it's a poor quality test.
So after thinking about this for a few days. I thought of using takeUntil()
to force the observable to plete and then test the expected result then.
For example:
describe('service', () => {
let finished: Subject<void>;
beforeEach(() => {
TestBed.configureTestingModule({providers: [MyService]});
finished = new Subject();
});
afterEach(() => {
finished.next();
finishedplete();
});
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);
}));
});
In the above example the value is being stored in a local variable and then the expected result is checked when the observable pletes. I force the pletion by using afterEach()
with takeUntil()
.
Question:
Are there any side effects with my approach, and if so what would be the more Angular/Jasmine way of performing these kinds of tests. I am worried that you are not suppose to perform expect assertions during the afterEach() life-cycle call.
I have a service that creates an observable that emits values, and it's relatively easy to test that an emitted value is as expected.
For example:
describe('service', () => {
beforeEach(() => {
TestBed.configureTestingModule({providers: [MyService]});
});
it('should emit true', async(() => {
const service = TestBed.get(MyService);
service.values$.subscribe((value) => expect(value).toBeTruthy());
}));
});
The above works to test the expected value, but it only works if the service actually emits a value. If you have the edge case where the service fails to emit a value, then the test itself actually passes and Jasmine logs the warning message "SPEC HAS NO EXPECTATIONS should be created".
I searched Google for a while trying to figure out how to catch this case as an error and came up with this approach.
it('should emit true', async(() => {
const service = TestBed.get(MyService);
let value;
service.values$.subscribe((v) => value = v);
expect(value).toBeTruthy();
}));
The above works only for synchronous observables and feels like code smell to me. Another developer will see this and think it's a poor quality test.
So after thinking about this for a few days. I thought of using takeUntil()
to force the observable to plete and then test the expected result then.
For example:
describe('service', () => {
let finished: Subject<void>;
beforeEach(() => {
TestBed.configureTestingModule({providers: [MyService]});
finished = new Subject();
});
afterEach(() => {
finished.next();
finished.plete();
});
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);
}));
});
In the above example the value is being stored in a local variable and then the expected result is checked when the observable pletes. I force the pletion by using afterEach()
with takeUntil()
.
Question:
Are there any side effects with my approach, and if so what would be the more Angular/Jasmine way of performing these kinds of tests. I am worried that you are not suppose to perform expect assertions during the afterEach() life-cycle call.
Share Improve this question asked Dec 18, 2018 at 13:37 ReactgularReactgular 54.9k24 gold badges173 silver badges218 bronze badges1 Answer
Reset to default 6This seems overkill to me.
Jasmine offers a callback in its tests, you could simply use it ?
it('should X', doneCallback => {
myObs.subscribe(res => {
expect(x).toBe(y);
doneCallback();
});
});
If the callback isn't called, the test fails with a timeout exception (meaning no more test will run after this failed one)
本文标签: javascriptTest that an Angular observable emits a value or sequenceStack Overflow
版权声明:本文标题:javascript - Test that an Angular observable emits a value or sequence - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744326207a2600738.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论