0

I am trying to test a function containing a Promise.all in jasmine (TypeScript, but I assume I'd have the same problem in JS) - I want to make sure I am handling a rejection appropriately:

function foo(): Promise<void> {
    return Promise.all(promise1, promise2)
        .catch(() => undefined)
        .then(() => undefined);
}

function bar() {
    foo().finally(makeBarHappen);
}

And then my test is something like this, where I mock one of the promises inside foo to fail:

it('test bar happens even when foo fails', async () => {
     mocks.promise1.and.returnValue(Promise.reject('loremipsum'));

     pressButtonThatTriggersBar();

     await timeout(longEnoughTimeoutForBarToHappen);

     expect(barHappened);
});

The problem is, I get an "Unhandled Rejection: loremipsum thrown" error from Jasmine - even though I believe I am handling the rejection with the catch() inside of foo? I shouldn't need individual catches for every promise inside the Promise.all, should I? I tested this manually and it does catch the rejection and behave appropriately, so I'm not sure the best way to test this in Jasmine. Thanks!

Nicole Stein
  • 925
  • 1
  • 9
  • 23
  • Your function `bar` is not returning a promise - that might be the problem since your code doesn't know it should be waiting for anything. – Kryten Sep 08 '20 at 15:13
  • *"I shouldn't need individual catches for every promise inside the Promise.all, should I?"* Correct, you don't. I don't think the unhandled rejection is coming from the code you've posted. The code in `foo` definitely converts rejection to fulfillment with `undefined`. – T.J. Crowder Sep 08 '20 at 15:13
  • @Kryten - The comments in the test suggest that the test is waiting. Separately, that doesn't explain the error message the OP reports. But Nicole, you should be getting an error from TypeScript on that (not the runtime error you're describing), since `bar` says it returns a promise but doesn't return anything... – T.J. Crowder Sep 08 '20 at 15:14
  • @Kryten and T.J. Crowder - Whoops, good catch. Unfortunately, that mistake was only in my pseudocode for this question, not in my real code. bar() actually doesn't return anything - I edited above. So that's not the issue. – Nicole Stein Sep 08 '20 at 15:22
  • @T.J.Crowder It's definitely coming from the code I posted. I updated the rejection to be "loremipsum" instead of undefined - the error then becomes "Unhandled Rejection: loremipsum thrown". – Nicole Stein Sep 08 '20 at 15:26
  • @NicoleStein - I was talking about the first code block. I can't speak to the Jasmine part, but `foo` **definitely** does not return a rejection. That suggests to me that you want to focus on the `mocks.promise1.and.returnValue` part and why it would appear not be connected to `foo`. – T.J. Crowder Sep 08 '20 at 15:32
  • 1
    @T.J.Crowder Thank you!!! This is the insight I was missing - that my Promise.reject from the tests was never even making it to my actual code before it was eaten by Jasmine and the test failed. I found the correct way to do this in Jasmine - they have a .throwError function. :-) – Nicole Stein Sep 08 '20 at 16:14

1 Answers1

1

Looks like the correct way to test that promise1 failed was:

mocks.promise1.and.throwError('');

The Promise.reject() was getting caught by Jasmine before it ever had time to be caught by my actual error handling code.

Nicole Stein
  • 925
  • 1
  • 9
  • 23