How to test async function with Sinon JS?

旧街凉风 提交于 2021-02-11 17:05:31

问题


Below is a minimal example of what I want to achieve: I want to test fn3() being called if the async function fn2() resolved (when calling fn1). But I somehow failed to do that with sinon's stub syntax. I would like to know what I misunderstood.

// System Under Test

export function fn1() {
    fn2().then(() => {
        fn3();
    });
}

export async function fn2() {
    return new Promise((resolve, reject) => {
        // expensive work
        resolve();
    });
}

export function fn3() {
    console.log("fn3");
}

// Test

import * as Page from "xxx";

it("test async", () => {
    // stub this async to isolate the SUT
    sinon.stub(Page, "fn2").resolves();
    const stub = sinon.stub(Page, "fn3");

    Page.fn1();

    sinon.assert.calledOnce(stub);
});


/*

    AssertError: expected fn3 to be called once but was called 0 times

      276 |         Page.fn1();
      277 |
    > 278 |         sinon.assert.calledOnce(stub);
          |                      ^
      279 |     });
      280 | });

      at Object.fail (node_modules/sinon/lib/sinon/assert.js:107:21)
      at failAssertion (node_modules/sinon/lib/sinon/assert.js:66:16)
      at Object.calledOnce (node_modules/sinon/lib/sinon/assert.js:92:13)
      at Object.<anonymous> (src/test.test.tsx:278:22)
*/

回答1:


As @jonrsharpe suggested, your sinon.assert.calledOnce(stub); will be called before the fn2 promise inside Page.fn1 is resolved (i.e. .then(() => { fn3(); }) is called), based of the JavaScript "single thread, event loop" nature. Here's an article for reference: https://dev.to/lydiahallie/javascript-visualized-promises-async-await-5gke.

You can try changing your code to:

    ...

    return Page.fn1().then(() => {
      sinon.assert.calledOnce(stub);
    });
    
    ...

or

it("test async", async () => {
    // stub this async to isolate the SUT
    sinon.stub(Page, "fn2").resolves();
    const stub = sinon.stub(Page, "fn3");

    await Page.fn1();

    sinon.assert.calledOnce(stub);
});

so that sinon.assert.calledOnce(stub); will be called after Page.fn1() is resolved.



来源:https://stackoverflow.com/questions/63353016/how-to-test-async-function-with-sinon-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!