开玩笑的resetModules()打破了react-router-dom上下文

时间:2019-06-19 09:59:19

标签: reactjs mocking react-router jestjs

我正在测试一个包含Link组件的组件。 它还需要Service.js提供的上下文。

代码如下:

import React from "react"
import { Link } from "react-router-dom"
import { Context } from "./Service"

const List: React.FC = () => (
    <Context.Consumer>
        {items => (
            <div>
                {items
                    .map(({ name, id }) => (
                        <Link
                            to={`/items/${id}`}
                            key={id}
                        >
                            <p>{name}</p>
                        </Link>
                    ))}
            </div>
        )}
    </Context.Consumer>
)

export default List

运行以下测试时,出现错误:

Invariant failed: You should not use <Link> outside a <Router>

测试:

import React from "react"
import renderer from "react-test-renderer"
import { MemoryRouter } from "react-router"

describe("<List>", () => {
    beforeEach(() => jest.resetModules())

    it("renders with zero items", () => {
        jest.doMock("./Service", () => ({
            Context: {
                Consumer: (props: any) => props.children([]),
            },
        }))
        const List = require("./List").default
        const tree = renderer
            .create(<MemoryRouter><List /></MemoryRouter>)
            .toJSON()        
        expect(tree).toMatchSnapshot()
    })

    it("renders with items", () => {
        jest.doMock("./Service", () => ({
            Context: {
                Consumer: (props: any) =>
                   props.children([{ name: "d", id: "d" }]),
            },
        }))
        const List = require("./List").default
        const tree = renderer
            // this line throws the error!
            .create(<MemoryRouter><List /></MemoryRouter>)
            .toJSON()        
        expect(tree).toMatchSnapshot()
    })
})

注意:如果我删除beforeEach(() => jest.resetModules()),则测试有效,但它忽略了第二个模拟,并使用空数组运行。

1 个答案:

答案 0 :(得分:1)

通过强制为每个测试重新导入路由器来解决:

    // ...
    const { MemoryRouter } = require("react-router")`
    const List = require("./List").default
    const tree = renderer
    // ...

虽然看起来很冗长。如果有的话,请添加一个更好的解决方案,谢谢!