简体   繁体   中英

How do I call a resolve in the callback of a mocked function?

Here is the function I am trying to test:

index.js :

import ThirdParty from 'third-party';

function Main(){}

Main.prototype.getStuff = function(){
   return new Promise((resolve, reject) => {
      this.getOtherStuff().then((data) => {
         // Business logic...
         const tpinstance = new ThirdParty();

         tpinstance.createThing().nestedFunction(null, () => {
             // This is where I'm resolving the outer function
             resolve({newdata: goodstuff});
         });
      });
   }
}

Main.prototype.getOtherStuff = function(){
   return new Promise((resolve, reject) => {
     resolve();
   })
}

I am failing to resolve the the promise from the outer most function so I'm getting this error:

Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.Error:

My Test

//index.spec.js
import ThirdParty from 'third-party';

jest.mock('third-party');

describe('Main', () => {
   describe('#getStuff', () => {
      test('Want this to pass', async () => {

         jest
           .spyOn(Main.prototype, "getOtherStuff")
           .mockImplementationOnce(() => Promise.resolve({ data: "value" }));

         const mockedThing = {
            // This implementation seems wrong to me.
            nestedFunction: jest.fn().mockImplementation(() => Promise.resolve())
         }

         jest
           .spyOn(ThirdParty.prototype, "createThing")
           .mockImplementation(() => (mockedThing))

         let instance = new Main();
         await instance.getStuff();

         //assertions -> I never get here cause it timesout
         expect(Main.prototype.getOtherStuff).toHaveBeenCalled();
      });
   });
});

How can I mock out nestedFunction in a way where I'll be resolving the outer function in a callback I pass to nestedFunction ?

Here is the unit test solution:

index.js :

import ThirdParty from "./third-party";

export default function Main() {}

Main.prototype.getStuff = function() {
  return new Promise((resolve, reject) => {
    this.getOtherStuff().then(data => {
      const tpinstance = new ThirdParty();
      tpinstance.createThing().nestedFunction(null, () => {
        const goodstuff = data;
        resolve({ newdata: goodstuff });
      });
    });
  });
};

Main.prototype.getOtherStuff = function() {
  return new Promise((resolve, reject) => {
    resolve();
  });
};

third-party.js :

export default function ThirdParty() {}

ThirdParty.prototype.createThing = function() {
  console.log("real create thing");
  return this;
};

ThirdParty.prototype.nestedFunction = function(arg, cb) {
  console.log("real nested function");
};

index.spec.js :

import Main from "./";
import ThirdParty from "./third-party";

jest.mock("./third-party.js", () => {
  const mThirdParth = {
    createThing: jest.fn().mockReturnThis(),
    nestedFunction: jest.fn()
  };
  return jest.fn(() => mThirdParth);
});

describe("Main", () => {
  describe("#getStuff", () => {
    afterEach(() => {
      jest.restoreAllMocks();
      jest.resetAllMocks();
    });
    it("should pass", async () => {
      jest
        .spyOn(Main.prototype, "getOtherStuff")
        .mockResolvedValueOnce({ data: "value" });

      let callback;
      const tpinstance = new ThirdParty();
      tpinstance.createThing().nestedFunction.mockImplementation((arg, cb) => {
        callback = cb;
        cb();
      });
      const instance = new Main();
      const pending = instance.getStuff();
      console.log(pending);
      const actual = await pending;
      expect(actual).toEqual({ newdata: { data: "value" } });
      expect(Main.prototype.getOtherStuff).toBeCalledTimes(1);
      expect(tpinstance.createThing).toHaveBeenCalled();
      expect(tpinstance.createThing().nestedFunction).toBeCalledWith(
        null,
        callback
      );
    });
  });
});

Unit test result with coverage report:

 PASS  src/stackoverflow/59150545/index.spec.js
  Main
    #getStuff
      ✓ should pass (12ms)

  console.log src/stackoverflow/59150545/index.spec.js:31
    Promise { <pending> }

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |    84.62 |      100 |    71.43 |    83.33 |                   |
 index.js |    84.62 |      100 |    71.43 |    83.33 |             18,19 |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        3.529s

Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59150545

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM