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

jim*_*mmy 5 javascript dom unit-testing reactjs jestjs

我想用玩笑测试以下代码。

有谁知道如何模拟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')
    );
}
Run Code Online (Sandbox Code Playgroud)

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

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

    );
}
Run Code Online (Sandbox Code Playgroud)

然后简单地测试estateList(),而不模拟document.getElementById(),但是有没有办法模拟document.getElementById()

sli*_*wp2 3

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

\n

例如

\n

index.tsx:

\n
import React from \'react\';\nimport { Provider } from \'react-redux\';\nimport { render } from \'react-dom\';\nimport { createStore } from \'redux\';\n\nexport const store = createStore(() => 0);\n\nexport const EstateList = () => <div>EstateList</div>;\nexport const ArticleList = () => <div>ArticleList</div>;\nexport const ArticleDetail = () => <div>ArticleDetail</div>;\n\nfunction bootstrap() {\n  if (document.getElementById(\'estateList\')) {\n    render(\n      <Provider store={store}>\n        <EstateList />\n      </Provider>,\n      window.document.getElementById(\'estateList\'),\n    );\n  }\n\n  if (document.getElementById(\'articleList\')) {\n    render(\n      <Provider store={store}>\n        <ArticleList />\n      </Provider>,\n      window.document.getElementById(\'articleList\'),\n    );\n  }\n\n  if (document.getElementById(\'articleDetail\')) {\n    render(\n      <Provider store={store}>\n        <ArticleDetail />\n      </Provider>,\n      window.document.getElementById(\'articleDetail\'),\n    );\n  }\n}\n\nexport { bootstrap };\n
Run Code Online (Sandbox Code Playgroud)\n

index.test.tsx:

\n
import React from \'react\';\nimport { render } from \'react-dom\';\nimport { bootstrap, store, EstateList, ArticleList, ArticleDetail } from \'./\';\nimport { Provider } from \'react-redux\';\n\njest.mock(\'react-dom\');\nconst mockedRender = render as jest.Mocked<typeof render>;\n\ndescribe(\'49146453\', () => {\n  let oGetElementById;\n  beforeAll(() => {\n    oGetElementById = document.getElementById;\n  });\n  afterAll(() => {\n    document.getElementById = oGetElementById;\n  });\n  it(\'should render estatelist\', () => {\n    document.getElementById = jest.fn().mockImplementation((id) => (id === \'estateList\' ? \'estateList-dom\' : null));\n    bootstrap();\n    expect(mockedRender).toBeCalledWith(\n      <Provider store={store}>\n        <EstateList />\n      </Provider>,\n      \'estateList-dom\',\n    );\n  });\n\n  it(\'should render articleList\', () => {\n    document.getElementById = jest.fn().mockImplementation((id) => (id === \'articleList\' ? \'articleList-dom\' : null));\n    bootstrap();\n    expect(mockedRender).toBeCalledWith(\n      <Provider store={store}>\n        <ArticleList />\n      </Provider>,\n      \'articleList-dom\',\n    );\n  });\n\n  it(\'should render articleDetail\', () => {\n    document.getElementById = jest.fn().mockImplementation((id) => (id === \'articleDetail\' ? \'articleDetail-dom\' : null));\n    bootstrap();\n    expect(mockedRender).toBeCalledWith(\n      <Provider store={store}>\n        <ArticleDetail />\n      </Provider>,\n      \'articleDetail-dom\',\n    );\n  });\n});\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
 PASS  src/stackoverflow/49146453/index.test.tsx\n  49146453\n    \xe2\x9c\x93 should render estatelist (6ms)\n    \xe2\x9c\x93 should render articleList (1ms)\n    \xe2\x9c\x93 should render articleDetail (1ms)\n\n-----------|----------|----------|----------|----------|-------------------|\nFile       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |\n-----------|----------|----------|----------|----------|-------------------|\nAll files  |    84.21 |      100 |       40 |      100 |                   |\n index.tsx |    84.21 |      100 |       40 |      100 |                   |\n-----------|----------|----------|----------|----------|-------------------|\nTest Suites: 1 passed, 1 total\nTests:       3 passed, 3 total\nSnapshots:   0 total\nTime:        5.618s, estimated 11s\n
Run Code Online (Sandbox Code Playgroud)\n

关于版本jest.js及相关包,查看源码: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/49146453

\n