【问题标题】:addEventHandler mocking in Jest & TypescriptJest 和 Typescript 中的 addEventHandler 模拟
【发布时间】:2020-07-27 07:31:13
【问题描述】:

这是一个普通的 TS 项目。没有框架。

我有followed through this article here,作者以此模拟addEventListener 方法(但是在窗口上)。

我很困惑为什么模拟函数没有注册为被调用。

 console.log
    called in here

      at Object.handleClick [as click] (src/painter/painter.ts:24:13)

 FAIL  src/painter/painter.test.ts
  Painter Setup
    ✕ Should add event handlers to canvas (14 ms)

  ● Painter Setup › Should add event handlers to canvas

    expect(received).toHaveBeenCalled()

    Matcher error: received value must be a mock or spy function

简化实现:

class Painter {
  constructor(target: HTMLCanvasElement) {
    this.canvas = target;
    //...
    this.init();
  }
  init() {
    this.canvas.addEventListener("click", this.handleClick);
  }
  // I know that the this context is wrong here, but trying to simplify the issue
  handleClick(event: MouseEvent) {
    console.log('called in here');
  };
}


// testing
const eventListeners: Record<string, Function> = {};

let canvas = document.createElement("canvas");

canvas.addEventListener = jest.fn((eventName: string, callBack: Function) => {
  eventListeners[eventName] = callBack;
}) as jest.Mock;


describe("Painter Setup", function () {
  it("Should add event handlers to canvas", () => {
    const painter = new Painter(canvas);
    eventListeners.click({
      clientX: 0,
      clientY: 0,
    });
    expect(painter.handleClick).toHaveBeenCalled();
  });
});

【问题讨论】:

    标签: typescript unit-testing mocking jestjs


    【解决方案1】:

    我认为缺少的步骤只是在 handleClick 方法上使用间谍,以注册该函数确实被调用。 handleClick 仍然是通过调用,而不是模拟它。

    // testing
    const eventListeners: Record<string, Function> = {};
    
    let canvas = document.createElement("canvas");
    
    canvas.addEventListener = jest.fn((eventName: string, callBack: Function) => {
      eventListeners[eventName] = callBack;
    }) as jest.Mock;
    
    describe("Painter Setup", function () {
      it("Should add event handlers to canvas", () => {
        const spied = jest.spyOn(Painter.prototype, 'handleClick');
        
        const painter = new Painter(canvas);
        
        // this will still call though the original method. Therefore I will see  "called in here" from painter.handleClick
        eventListeners.click({
          clientX: 0,
          clientY: 0,
        });
       
        expect(spied).toHaveBeenCalled(); 
      });
    });
    

    【讨论】:

      【解决方案2】:

      错误表明toHaveBeenCalled()(即painter.handleClick)收到的参数应该是模拟/间谍,但事实并非如此。

      您可以在测试中将handleClick 设置为模拟函数:

      it('...', () => {
        Painter.prototype.handleClick = jest.fn(); // mock handleClick
        const painter = new Painter(canvas);
      
        //...
        expect(painter.handleClick).toHaveBeenCalled();
      })
      

      【讨论】:

      • 虽然这确实有效,但这不会通过原始方法调用。我应该期待在控制台中看到'called in here'。不过,你给了我一个想法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-14
      • 2021-04-05
      • 2018-07-23
      • 2020-03-18
      • 2018-08-08
      • 2018-12-18
      相关资源
      最近更新 更多