【问题标题】:Jest: test if callback function from addEventListener was called开玩笑:测试是否调用了 addEventListener 的回调函数
【发布时间】:2020-12-16 04:15:05
【问题描述】:

我有下一个功能:

const hashChangeCallback = event => {
   console.log('event', event.oldUrl)
}

const hashHandler = () => {
  return {
    add: () => {
      window.addEventListener('hashchange', (event) => hashChangeCallback(event), false)
    },
    remove: () => {
      window.removeEventListener('hashchange', (event) => hashChangeCallback(event), false)
    },
  }
}

在我的 Jest 测试中,我想检查是否在触发事件时调用了 hashChangeCallback 函数:

import { hashHandler } from './urlHashChangeListener'

describe('urlHashChangeListener', () => {
  const setupHashListeners = hashHandler()


  it('hashChangeCallback should be called when hash changed if listener is added', () => {
    setupHashListeners.add()

    window.dispatchEvent(new HashChangeEvent('hashchange', {
      oldURL: 'http://test.com/test.html#hash123', 
      newURL: 'http://test.com/test.html#hash3'
    }))

    // expect hashChangeCallback to be called
  })
})

如何正确操作?我是否必须以某种方式模拟/监视此功能?

【问题讨论】:

  • 不模拟 addEventListener 是不可能的。 hashChangeCallback 是本地的,因此在测试中无法访问。在您发布的案例中没有意义。只需测试 console.log 是否被调用。

标签: javascript testing jestjs enzyme


【解决方案1】:

如果hashChangeCallback 函数未导出,则无法模拟或窥探它。可以通过断言console.log是否被调用来间接断言hashChangeCallback是否被调用。

此外,它应该是event.oldURL 而不是event.oldUrl

例如

urlHashChangeListener.ts:

const hashChangeCallback = (event) => {
  console.log('event', event.oldURL);
};

export const hashHandler = () => {
  return {
    add: () => {
      window.addEventListener('hashchange', (event) => hashChangeCallback(event), false);
    },
    remove: () => {
      window.removeEventListener('hashchange', (event) => hashChangeCallback(event), false);
    },
  };
};

urlHashChangeListener.test.ts:

import { hashHandler } from './urlHashChangeListener';

describe('urlHashChangeListener', () => {
  const setupHashListeners = hashHandler();

  it('hashChangeCallback should be called when hash changed if listener is added', () => {
    const logSpy = jest.spyOn(console, 'log');
    setupHashListeners.add();

    window.dispatchEvent(
      new HashChangeEvent('hashchange', {
        oldURL: 'http://test.com/test.html#hash123',
        newURL: 'http://test.com/test.html#hash3',
      })
    );

    expect(logSpy).toBeCalledWith('event', 'http://test.com/test.html#hash123');
    logSpy.mockRestore();
  });
});

测试结果:

 PASS  examples/63613274/urlHashChangeListener.test.ts (7.068 s)
  urlHashChangeListener
    ✓ hashChangeCallback should be called when hash changed if listener is added (17 ms)

  console.log
    event http://test.com/test.html#hash123

      at console.<anonymous> (node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866:25)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        7.745 s, estimated 8 s

软件包版本:

"enzyme": "^3.11.0",
"jest": "^26.6.3"

【讨论】:

    【解决方案2】:

    您可以概括您的功能,使您的测试更容易一些并减少重复:

    const controlListener = event => fn => ({
        add: () => window.addEventListener(event, fn, false),
        remove: () => window.removeEventListener(event, fn, false),
      })
    
    export const hashListener = controlListener('hashchange')
    
    // In your production code
    const hashHandler = hashListener(hashChangeCallback)
    
    // In your test file
    const mockHashChangeCallback = jest.fn()
    const hashHandler = hashListener(mockHashChangeCallback)
    expect(mockHashChangeCallback.mock.calls).toEqual([...])
    

    【讨论】:

      猜你喜欢
      • 2021-04-03
      • 1970-01-01
      • 2019-07-16
      • 2021-12-11
      • 1970-01-01
      • 2020-12-17
      • 1970-01-01
      • 2020-08-16
      • 2019-09-15
      相关资源
      最近更新 更多