Assuming I have a function which calls two dependend async functions
function targetFn() {
asyncFn1();
asyncFn2();
}
This is clearly a defect, since asyncFn2
does not wait for asyncFn1
to be completed. The correct implementation would be:
function targetFn() {
asyncFn1().then(asyncFn2);
}
However, how to test this? Maybe I test it like this:
it("ensures the ordering", function() {
spyOn(window, "asyncFn1").and.callFake(function() {
return $q.reject("irrelevant");
});
spyOn(window, "asyncFn2");
$timeout.flush();
expect(asyncFn2).not.toHaveBeenCalled();
});
This is okay for this simple test case. But what if I have several chained async functions? The test effort would grow exponential; I have to test every possible combination of rejection and resolving for every promise. What if I change a sync function so that it is an async function afterwards? I would introduce a defect behavior in every callee function without any failing tests.
What I really want is an automatic detection of unhandled promises. Going back to the first example:
function targetFn() {
asyncFn1();
asyncFn2();
}
The test system should recognizes that asyncFn1
and asyncFn2
are creating new promises, but that there are no then
and catch
handler. Also the second example should of course fail:
function targetFn() {
asyncFn1().then(asyncFn2);
}
Because the then
introduces a new promise which is not handled, since it is not returned.
I would like to write a test like:
it("does not introduce unhandled promises", function() {
expect(targetFn).doesNotIntroduceUnhandledPromises();
});
And it checks if every promise created during the execution of targetFn
has either an "endpoint" like a finally
or is chained to the promises returned by the targetFn
.
Do you have any idea how to achive this? Or even a better solution for this?
Thanks
Timo