Search code examples
javascriptunit-testingmocha.jses6-promisesinon-chai

Async Function stubbing in sinon invokes actual function call


I have an async function when I run unit test with mocha,I see it is not stubbing it.I don't see console.log is printing the log in function,It looks like actual getUser() function is getting called.

// User.js

class User {
  async _getUser(client, email) {
    let result = await new userApi().getUser(new UserInfo(email, email));
    console.log("Get result " + JSON.stringify(result));
    let user = result.users[0];

    console.log("Get User " + JSON.stringify(user));
    return user;
  }
}
module.exports = User;


// Usertest.js

const chai = require("chai");
const sinon = require("sinon");
var chaiAsPromised = require("chai-as-promised");
chai.use(chaiAsPromised).should();
const expect = chai.expect;
const UserInfo = require("../src/model/userInfo");
const User = require("../src/model/user");

describe("Test LogInCommand", function() {
  let user, sandbox;

  beforeEach(() => {
    sandbox = sinon.sandbox.create();
    user = new user();
  });

  afterEach(function afterEach() {
    sandbox.restore();
  });

  it("getUser function", function(done) {
    let User = new UserInfo("email", "email", "station");
    sandbox
      .stub(userApi, "getUser")
      .withArgs(User)
      .returns(
        Promise.resolve({
          users: [
            {
              id: 1
            }
          ]
        })
      );
    sandbox.stub(logger, "info");
    let result = logInCommand._getUser(client, "email", "stationid");
    done();
  });
});

Solution

  • I assume that userApi is a class so in order to stub it, we must do like below:

    sandbox.stub(userApi.prototype, "getUser").withArgs(User)...
    

    we must add prototype to stub a method of class.

    I also find something to fix in your test, it is because you don't treat logInCommand._getUser as async call. So, here is the code after updated.

    it("getUser function", async function() { // remove `done` and let's use async/await here
      let User = new UserInfo("email", "email", "station");
      sandbox
        .stub(userApi.prototype, "getUser") // add prototype
        .withArgs(User)
        .resolves({ // in new sinon, they have `resolves` method
            users: [
              {
                id: 1
              }
            ]
          });    
      sandbox.stub(logger, "info");
      let result = await logInCommand._getUser(client, "email", "stationid"); // add await because this method is async
      // remove done()
    });
    

    Hope it helps