Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to spy an async function and assert that it throws an error by sinon?

I'm trying to use Mocha with ts-node to write unit-test in TypeScript for my project. When I use sinon to make a spy to an async function, I can't get the test pass. Below is my code

class MyClass {
    async businessFunction(param): Promise<void> {
        if (!param)  //Validate the input
          throw new Error("input must be valid");

        // Then do my business
    }
}

And the unit-test

describe("The feature name", () => {
    it("The case of invalid", async () => {
        const theObject = new MyClass();
        const theSpider = sinon.spy(theObject, "businessFunction");
        try {
            await theObject.businessFunction(undefined);
        } catch (error) {/* Expected error */}
        try {
            await theObject.businessFunction(null);
        } catch (error) {/* Expected error */}

        sinon.assert.calledTwice(theSpider); // => Passed
        sinon.assert.alwaysThrew(theSpider); // => Failed, why?

        theSpider.restore();
    });
});

Has anyone had experience to deal with this? I've been suggested to make checks with catched errors, but it seems be complex and make the check code be duplicated unnecessarily.

like image 895
hlv_trinh Avatar asked Nov 16 '25 13:11

hlv_trinh


1 Answers

Your function is an async function.

The docs for async functions state that they will return:

A Promise which will be resolved with the value returned by the async function, or rejected with an uncaught exception thrown from within the async function.


In other words, your function does not throw an error, it returns a Promise that will reject with the error.


Since you are using Mocha you can use something like .rejected from chai-as-promised to test that the Promise returned by your async function rejects:

it("The case of invalid", async () => {
  const theObject = new MyClass();

  await theObject.businessFunction(undefined).should.be.rejected;  // SUCCESS
  await theObject.businessFunction(null).should.be.rejected;  // SUCCESS
});
like image 88
Brian Adams Avatar answered Nov 18 '25 09:11

Brian Adams



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!