单元测试:如何在反应中模拟document.getElementById()?

时间:2018-03-07 07:34:26

标签: reactjs unit-testing jest

我想用jest测试以下代码。

anynoe是否知道如何模拟 document.getElementById()

if (document.getElementById('estateList')) {
    render(
        <Provider store={store}>
            <EstateList />
        </Provider>,
        window.document.getElementById('estateList')
    );
}


if (document.getElementById('articleList')) {
    render(
        <Provider store={store}>
            <ArticleList />
        </Provider>,
        window.document.getElementById('articleList')
    );
}

if (document.getElementById('articleDetail')) {
    render(
        <Provider store={store}>
            <ArticleDetail />
        </Provider>,
        window.document.getElementById('articleDetail')
    );
}

我想我可以将渲染放在一个函数中,例如:

function estateList() {
    render(
        <Provider store={store}>
            <EstateList />
        </Provider>,
        window.document.getElementById('estateList')

    );
}

然后简单地测试estateList(),而不模仿 document.getElementById(),但是无论如何都要模拟 document.getElementById()

1 个答案:

答案 0 :(得分:0)

使用jest.fn(implementation)创建模拟的getElementById方法并替换document上的方法。

例如

index.tsx

import React from 'react';
import { Provider } from 'react-redux';
import { render } from 'react-dom';
import { createStore } from 'redux';

export const store = createStore(() => 0);

export const EstateList = () => <div>EstateList</div>;
export const ArticleList = () => <div>ArticleList</div>;
export const ArticleDetail = () => <div>ArticleDetail</div>;

function bootstrap() {
  if (document.getElementById('estateList')) {
    render(
      <Provider store={store}>
        <EstateList />
      </Provider>,
      window.document.getElementById('estateList'),
    );
  }

  if (document.getElementById('articleList')) {
    render(
      <Provider store={store}>
        <ArticleList />
      </Provider>,
      window.document.getElementById('articleList'),
    );
  }

  if (document.getElementById('articleDetail')) {
    render(
      <Provider store={store}>
        <ArticleDetail />
      </Provider>,
      window.document.getElementById('articleDetail'),
    );
  }
}

export { bootstrap };

index.test.tsx

import React from 'react';
import { render } from 'react-dom';
import { bootstrap, store, EstateList, ArticleList, ArticleDetail } from './';
import { Provider } from 'react-redux';

jest.mock('react-dom');
const mockedRender = render as jest.Mocked<typeof render>;

describe('49146453', () => {
  let oGetElementById;
  beforeAll(() => {
    oGetElementById = document.getElementById;
  });
  afterAll(() => {
    document.getElementById = oGetElementById;
  });
  it('should render estatelist', () => {
    document.getElementById = jest.fn().mockImplementation((id) => (id === 'estateList' ? 'estateList-dom' : null));
    bootstrap();
    expect(mockedRender).toBeCalledWith(
      <Provider store={store}>
        <EstateList />
      </Provider>,
      'estateList-dom',
    );
  });

  it('should render articleList', () => {
    document.getElementById = jest.fn().mockImplementation((id) => (id === 'articleList' ? 'articleList-dom' : null));
    bootstrap();
    expect(mockedRender).toBeCalledWith(
      <Provider store={store}>
        <ArticleList />
      </Provider>,
      'articleList-dom',
    );
  });

  it('should render articleDetail', () => {
    document.getElementById = jest.fn().mockImplementation((id) => (id === 'articleDetail' ? 'articleDetail-dom' : null));
    bootstrap();
    expect(mockedRender).toBeCalledWith(
      <Provider store={store}>
        <ArticleDetail />
      </Provider>,
      'articleDetail-dom',
    );
  });
});

具有覆盖率报告的单元测试结果:

 PASS  src/stackoverflow/49146453/index.test.tsx
  49146453
    ✓ should render estatelist (6ms)
    ✓ should render articleList (1ms)
    ✓ should render articleDetail (1ms)

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |    84.21 |      100 |       40 |      100 |                   |
 index.tsx |    84.21 |      100 |       40 |      100 |                   |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       3 passed, 3 total
Snapshots:   0 total
Time:        5.618s, estimated 11s

有关jest.js和相关软件包的版本,请检查源代码:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/49146453