Search code examples
node.jsunit-testingmocha.jssinon

Sinin does not return the right number forhow many times a function got called


I have a code as follows:

 public async cleanUpCachedData(){
    
    const queries = await this._searchesDatastore.getArchivedSearches();
    queries.forEach(async query => {
        try{
            // try catch for each is neccessary 
            await this.handleCacheCleanup("columns", query._id);
            console.log("################")
            await this.handleCacheCleanup("json", query._id);
            console.log("################")
            await this.handleCacheCleanup("stix", query._id);
            console.log("################")
            await this.handleCacheCleanup("summary", query._id);
            console.log("################")
            await this.handleCacheCleanup("timechart", query._id);
            console.log("################")

and I wrote a test:

  it("Successful handling cache data clean up process", async () => {

    const searchDatastoreObj = searchesDatastore;
    const getArchivedSearchesStub = sandbox
      .stub(searchDatastoreObj, "getArchivedSearches")
      .returns([{_id: "11111"}]);
    const obj = initCache(
      loggingService,
      searchesDatastore,
      resultsDatastoreObj,
    );

    const test = sandbox
    .stub(obj, "handleCacheCleanup").returns(true)
    
    await obj.cleanUpCachedData();
    expect(getArchivedSearchesStub.calledOnce).to.be.true;
    expect(test.callCount).to.equal(5);
    
  });

As you I have 5 handleCacheCleanup function call and I can see ################ printed 5 times but the test claims that it runs twice

  1) test cache cleanup by Total disk space
       Successful handling cache data clean up process:

      AssertionError: expected 2 to equal 5
      + expected - actual

      -2
      +5

I am really confused any idea


Solution

  • Even though you have it as async, the queries.forEach is being treated as sync and Promise resolve/rejection being ignored. Possible way to adjust this is using Promise.all().

    await Promise.all(queries.map(query => {
        try{
            // try catch for each is neccessary 
            await this.handleCacheCleanup("columns", query._id);
            console.log("################")
            await this.handleCacheCleanup("json", query._id);
            console.log("################")
            await this.handleCacheCleanup("stix", query._id);
            console.log("################")
            await this.handleCacheCleanup("summary", query._id);
            console.log("################")
            await this.handleCacheCleanup("timechart", query._id);
            console.log("################")
        } catch (e) {}
    })
    

    It executed the 5 calls to your point of console logging, but the test case completed before all of promises resolved. forEach is not async, so it got executed, but didn't wait for all promises inside to complete.