如何在 React 功能组件中模拟 ipcRenderer.on 函数

Ant*_*iev 3 mocking reactjs jestjs electron react-testing-library

我正在编写一个 Electron 应用程序,使用 React 作为前端,使用 JEST + React 测试库来运行测试。我在模块中有以下简化代码:

import React from 'react';
import { ipcRenderer } from 'electron';
import Paper from '@material-ui/core/Paper';
import LinearProgress from '@material-ui/core/LinearProgress';


const AccountCheckModule = () => {

  const [listingsCount, setListingsCount] = React.useState(0);

  React.useEffect(() => {
    ipcRenderer.on('count-listings', (event, count) => {
      setListingsCount(count);
    });

    ipcRenderer.send('count-listings');

    // Cleanup the listener events so that memory leaks are avoided.
    return function cleanup() {
      ipcRenderer.removeAllListeners('count-listings');
    };
  }, []);

  return (
    <Paper elevation={2} data-testid="paper">
        <p
          className={classes.listingsNumberTracker}
          data-testid="free-listings-counter"
        >
          Free listings: {listingsCount}/100
        </p>
        <BorderLinearProgress
          className={classes.margin}
          variant="determinate"
          color="secondary"
          value={listingsCount}
          data-testid="border-linear-progress"
        />
    </Paper>
  );
};

export default AccountCheckModule;

Run Code Online (Sandbox Code Playgroud)

基本上,React.useEffect()运行一次,调用ipcRenderer.send('count-listings');并设置一个侦听器以等待主进程的响应。主进程以列表计数进行响应,收到后用于更新列表计数状态 ->setListingsCount(count)

是否可以使用 Jest 模拟此侦听器函数以返回“计数”数字。

ipcRenderer.on('count-listings', (event, count) => {
    setListingsCount(count);
});
Run Code Online (Sandbox Code Playgroud)

如果是,您将如何实现这一目标?

sli*_*wp2 5

这是一个单元测试解决方案,我创建了一个简单的electron模块来模拟真实的electron节点模块并简化您的组件 JSX 元素。

\n\n

例如

\n\n

index.tsx:

\n\n
import React from \'react\';\nimport { ipcRenderer } from \'./electron\';\n\nconst AccountCheckModule = () => {\n  const [listingsCount, setListingsCount] = React.useState(0);\n\n  React.useEffect(() => {\n    ipcRenderer.on(\'count-listings\', (event, count) => {\n      setListingsCount(count);\n    });\n\n    ipcRenderer.send(\'count-listings\', 2);\n\n    // Cleanup the listener events so that memory leaks are avoided.\n    return function cleanup() {\n      ipcRenderer.removeAllListeners(\'count-listings\');\n    };\n  }, []);\n\n  return <div>{listingsCount}</div>;\n};\n\nexport default AccountCheckModule;\n
Run Code Online (Sandbox Code Playgroud)\n\n

electron.ts:

\n\n
export const ipcRenderer = {\n  events: {},\n  on(event, handler) {\n    this.events[event] = handler;\n  },\n  send(event, data) {\n    this.events[event](event, data);\n  },\n  removeAllListeners(event) {\n    this.events[event] = undefined;\n  }\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

index.spec.tsx:

\n\n
import React from \'react\';\nimport { render, act } from \'@testing-library/react\';\nimport { ipcRenderer } from \'./electron\';\nimport AccountCheckModule from \'./\';\n\ndescribe(\'AccountCheckModule\', () => {\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n  it(\'should render correct\', async () => {\n    const events = {};\n    const onSpy = jest.spyOn(ipcRenderer, \'on\').mockImplementation((event, handler) => {\n      events[event] = handler;\n    });\n    const sendSpy = jest.spyOn(ipcRenderer, \'send\').mockImplementation((event, data) => {\n      events[event](event, data);\n    });\n    const { getByText, container } = render(<AccountCheckModule></AccountCheckModule>);\n    const mCount = 666;\n    act(() => {\n      ipcRenderer.send(\'count-listings\', mCount);\n    });\n    const element = getByText(mCount.toString());\n    expect(element).toBeDefined();\n    expect(onSpy).toBeCalledWith(\'count-listings\', expect.any(Function));\n    expect(sendSpy).toBeCalledWith(\'count-listings\', mCount);\n    expect(container).toMatchSnapshot();\n  });\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

SFC 的单元测试结果和 100% 覆盖率报告:

\n\n
PASS  src/stackoverflow/58048849/index.spec.tsx\n  AccountCheckModule\n    \xe2\x9c\x93 should render correct (47ms)\n\n-------------|----------|----------|----------|----------|-------------------|\nFile         |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |\n-------------|----------|----------|----------|----------|-------------------|\nAll files    |    88.89 |      100 |    71.43 |     87.5 |                   |\n electron.ts |       50 |      100 |    33.33 |       50 |               4,7 |\n index.tsx   |      100 |      100 |      100 |      100 |                   |\n-------------|----------|----------|----------|----------|-------------------|\nTest Suites: 1 passed, 1 total\nTests:       1 passed, 1 total\nSnapshots:   1 passed, 1 total\nTime:        4.247s, estimated 11s\n
Run Code Online (Sandbox Code Playgroud)\n\n

index.spec.tsx.snap:

\n\n
// Jest Snapshot v1\n\nexports[`AccountCheckModule should render correct 1`] = `\n<div>\n  <div>\n    666\n  </div>\n</div>\n`;\n
Run Code Online (Sandbox Code Playgroud)\n\n

源代码:https ://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58048849

\n