代码之家  ›  专栏  ›  技术社区  ›  Jake

如何模拟在测试类中创建的API客户机?

  •  0
  • Jake  · 技术社区  · 5 年前

    我有一个如下的组件类,它使用第三方npm模块创建rest和websocket连接。我可以改变主意组件.构造函数接受模块作为依赖项,以便在Jest测试期间插入模拟版本。但我读到有关嘲弄的笑话,我想我想尝试一下,但我似乎不明白如何拦截Api休息()和Api.Websocket返回值。

    // component.ts
    import * as Api from 'npm-module'
    import * as wait from 'wait-for-stuff' // actual npm module
    export class Component {
        private _rest:any;
        private _websocket:any;
        public events = new EventEmitter();
        constructor() {
            // I want to intecept the return value of
            // Api.Rest() and Api.Websocket() to use mock versions.
            this._rest = new Api.Rest();
            this._websocket = new Api.Websocket();
    
            this._init();
        }
    
        private _init() {
            // so that when do stuff with this._rest and this._websocket;
            // I can control what is the expected results during test
            this._websocket.onUpdate((data) => {
                events.emit('update', data);
            });
            var value = wait.for.promise(this._rest.getSomething());
        }
    }
    

    0 回复  |  直到 5 年前
        1
  •  2
  •   Brian Adams    5 年前

    下面是一个简化的工作示例,让您开始:

    // @ts-ignore
    import * as Api from 'npm-module';  // <= (ts-ignore since "npm-module" doesn't exist)
    import EventEmitter from 'events';
    
    jest.mock('npm-module', () => {
      const getSomethingMock = jest.fn();  // <= always return...
      const onUpdateMock = jest.fn();  // <= ...the same mocks...
      return {
        Rest: () => ({ getSomething: getSomethingMock }),
        Websocket: () => ({ onUpdate: onUpdateMock })
      }
    },
    { virtual: true });  // <= (use virtual since "npm-module" doesn't exist)
    
    class Component {
      private _rest: any;
      private _websocket: any;
      public events = new EventEmitter();
      constructor() {
        this._rest = new Api.Rest();
        this._websocket = new Api.Websocket();
        this._init();
      }
    
      private _init() {
        this._websocket.onUpdate((data) => {  // <= ...so that this onUpdate...
          this.events.emit('update', data);
        });
      }
    }
    
    test('Component', () => {
      const component = new Component();
      const listener = jest.fn();
      component.events.on('update', listener);
      const onUpdate = new Api.Websocket().onUpdate;  // <= ...is the same as this one
      const onUpdateArrowFunction = onUpdate.mock.calls[0][0];  // <= get the arrow function passed to it
      onUpdateArrowFunction('mock data');  // <= now call the function
      expect(listener).toHaveBeenCalledWith('mock data');  // Success!
    });
    

    细节

    Jest 接管 require 系统,并允许您指定在需要模块时希望它返回的内容(请注意,TypeScript import 语句被编译为 电话)。

    模拟模块的一种方法是创建 manual mock __mocks__/npm-module.ts 里面有你的嘲笑。

    jest.mock 并给它传递一个模块工厂函数。

    开玩笑 将返回模拟模块。

    注意,上面的例子总是返回相同的mock getSomething onUpdate

    还要注意 mockFn.mock.calls 要检索此箭头函数:

    (data) => {
      this.events.emit('update', data);
    }
    

    …传递给 更新 . 一旦检索到它,就可以直接调用它,从而按预期触发侦听器。