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
 
    