如何模拟外部模块

时间:2019-06-10 23:44:28

标签: typescript jestjs

我很难弄清楚如何在模块中的函数被调用时调用外部库方法。

给出此打字稿类:

import transport from "app/customApiLibrary";
const { api } = transport;

// myServiceClass.ts
export class MyServiceClass {
  getSomeStuff(): Promise<any> {
    return api.get("myservice/end/point/");
  }

}
let serviceStuff = new MyServiceClass();
export default serviceStuff;

如何测试执行getSomeStuff时是否调用了api.get?

我尝试了spyOn,但是没有用。 而且我认为这不是正确的方法。 我认为简单地模拟传输的api方法就是方法,但是我不知道如何构建该模拟。

// const spy = jest.spyOn(transport, "get"); 
// doesn´t work.  Cannot spy the get property because it is not a function; undefined given instead

// myServiceClass.spec.ts
import serviceStuff from "./myServiceClass";
import transport from "app/util/transport";

describe("MyServiceClass", () => {
  it("when getSomeStuff", () => {
    expect(serviceStuff.getSomeStuff).toBeDefined(); // checks
    serviceStuff.getSomeStuff();
    // expect(spy).toHaveBeenCalled(); see above
  });
});

我尝试了这种模拟的一些令人尴尬的变化:

jest.mock('app/util/transport', () => ({
  api: class {
     get() {
      return {
        promise: true,
      };
    }
  },
}));

但我不断得到:

  

TypeError:无法读取未定义的属性“ get”

1 个答案:

答案 0 :(得分:0)

您做得差不多。

首先,如果模块本身位于default中,则无法通过在transport之类的模块路径中指定jest.mock('app/util/transport')来模拟'app/customApiLibrary'导出。但这可能只是在将实际代码引入Stackoverflow问题中时的一个偶然错误...

示例代码中的transport是从“ app / customApiLibrary”默认导出的。要模拟默认导出,您可以明确地进行以下操作:

jest.mock('app/customApiLibrary', () => ({
  default: {
    api: class {
     get: jest.fn(() => ({
         promise: true,
       })),
     }
  }
}));

或者可以在jest.mock中使用返回函数的功能(我个人从来没有那样做,但是有可能articles say

jest.mock('app/customApiLibrary', () => () => ({
  api: class {
   get: jest.fn(() => ({
       promise: true,
     })),
   }
}));

看,我将get声明为jest.fn()

这意味着在it()中,我可以检查它是否已被调用:

import transport from `app/customApiLibrary`;

jest.mock(...)

it('do', () => {
    // doing something
    // check any call for parameters
    expect(transport.api.get).toHaveBeenCalledWith('param1', 'param2');
    // or check if it has been called particular amount of times
    expect(transport.api.get).toHaveBeenCalledTimes(3);
    // or event verify specific calls or particular params by accessing `.mock.calls` prop
    expect(transport.api.get.mock.calls[0][1]).toEqual('_temp_')

})

为确保每次都需要清除呼叫计数,我们需要清除该数据:

beforeEach(() => {
  transport.api.get.mockClear();
})

如果没有spyOn或将功能设置为jest.fn,将是不可能的。