Search code examples
javascriptrecursionsettimeoutsinon

Sinon , recursion and setTimeout


I looked through stackoverflow for this question, but seems like majority of the questions cover two out of the three, and most people don't have a need to use all three.

This is the code snippet. I am trying to have testA to recursively call itself after a certain timeout.

const testA = async () => {
  setTimeout(() => {
    testA();
  }, 1000);
  return;
};

Here's my test code:

//test.js
const someThing = require("../tester.js");
const chai = require("chai");
const sinonChai = require("sinon-chai");
const sinon = require("sinon");
chai.use(sinonChai);

describe("Test A", () => {
  it("Should call twice", () => {
    const clock = sinon.useFakeTimers();
    const testASpy = sinon.spy(someThing, "testA");

    testASpy();
    chai.expect(testASpy).to.have.been.calledOnce; //is fine
    clock.tick(1000);
    chai.expect(testASpy).to.have.been.calledTwice; //fails
  });
});

I keep seeing everyone saying "Sinon cannot stub a standalone function" but I can't find out why. If someone could point me to the direction of reading more about it, I'd really like to see that. At the same time if anyone knows a work around to make this work, I'd love to know more as well. Thanks again!


Solution

  • Your code does not make sense. It will cause infinite loop. Here is the unit test solution:

    index.ts:

    export const testA = async () => {
      setTimeout(() => {
        console.count("testA");
        testA();
      }, 1000);
    };
    

    index.spec.ts:

    import * as mod from "./";
    import sinon from "sinon";
    import { expect } from "chai";
    
    describe("58843454", () => {
      it("should pass", async () => {
        const clock = sinon.useFakeTimers();
        const testASpy = sinon.spy(mod, "testA");
        await testASpy();
        expect(testASpy.calledOnce).to.be.true;
        clock.tick(1000);
        expect(testASpy.calledTwice).to.be.true;
      });
    });
    

    Unit test result with 100% coverage:

     58843454
    testA: 1
        ✓ should pass
    
    
      1 passing (16ms)
    
    ---------------|----------|----------|----------|----------|-------------------|
    File           |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
    ---------------|----------|----------|----------|----------|-------------------|
    All files      |      100 |      100 |      100 |      100 |                   |
     index.spec.ts |      100 |      100 |      100 |      100 |                   |
     index.ts      |      100 |      100 |      100 |      100 |                   |
    ---------------|----------|----------|----------|----------|-------------------|
    

    Source code: https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/58843454