javascript - 使用 React、react-router、jest 和 enzyme 测试状态变化

标签 javascript unit-testing reactjs react-router enzyme

我正在尝试通过测试验证有状态组件的状态在 componentDidMount 中是否已适当更改, 但由于 react-router 撞墙了。

我正在使用 enzyme ,所以我使用 mount为了评估生命周期方法,例如 componentDidMount .通常,这工作得很好......

it("changes state after mount", () => {
  const newValue = "new value";

  const testPropertyRetriever = () => newValue;

  const wrapper = mount(
      <StatefulPage
        myProperty="initial value"
        propertyRetriever={testPropertyRetriever}
      />
  );

  // componentDidMount should have executed and changed the state's myProperty value
  //     from "initial value" to "new value"
  expect(wrapper.instance().state.myProperty).toEqual(newValue);
});

...但是有问题的组件有问题,因为 mount渲染一对夫妇的 child ,在这种情况下,其中一个后代使用 react-router 的 <Link> .因此,运行上述测试会导致错误:TypeError: Cannot read property 'history' of undefinedFailed context type: The context `router` is marked as required in `Link`, but its value is `undefined`.

react-router docs建议使用 <Link> 包围需要上下文的组件的测试渲染(例如,使用 react-router 的 <MemoryRouter> )或 <StaticRouter> ,但这不会起作用,因为这会使被测组件成为子组件而不是 ReactWrapper 的根,这使得(据我所知)无法检索被测组件的状态。 (鉴于上面的例子......

// ...
const wrapper = mount(
  <MemoryRouter>
    <StatefulPage
      myProperty="initial value"
      propertyRetriever={testPropertyRetriever}
    />
  </MemoryRouter>
);

expect(wrapper.childAt(0).instance().state.myProperty).toEqual(newValue);

...测试失败,错误为 ReactWrapper::instance() can only be called on the root ).

我很快了解到 enzyme 的 mount采用允许将上下文传递到渲染器的选项参数,这是 react 路由器所需要的。所以我尝试删除路由器遏制并提供上下文(基于 this answer )...

//...
const wrapper = mount(
  <StatefulPage
    myProperty="initial value"
    propertyRetriever={testPropertyRetriever}
  />,
  { router: { isActive: true } }
);

expect(wrapper.instance().state.myProperty).toEqual(newValue);

...但这会导致与我开始时相同的关于上下文类型的错误。要么我没有正确传递上下文,要么我不知道如何将上下文传递给需要它的后代,要么没有办法(使用这些工具)所以。

从这里开始,我一直在寻找有关如何对上下文进行 stub 或模拟其中一个组件的详细信息,但未能有效地拼凑拼图以成功编写和运行此测试。

如何验证由 componentDidMount 更改的组件状态当它的后代依赖于满足 react-router 模块的上下文时?

最佳答案

提供给挂载函数的路由器定义不完整。

const MountOptions = {
    context: {
        router: {
            history: {
                createHref: (a, b) => {
                },
                push: () => {
                },
                replace: () => {
                }
            }
        }
    }, childContextTypes: {
        router: PropTypes.object
    }
};
const wrapper = mount(
    <StatefulPage
        myProperty="initial value"
        propertyRetriever={testPropertyRetriever}
    />,
    MountOptions
);

关于javascript - 使用 React、react-router、jest 和 enzyme 测试状态变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44710111/

相关文章:

silverlight - 为什么我的 Windows Phone 7 单元测试都没有运行?

javascript - 我想在单击复选框时传递一个 id 参数

javascript - React-redux 递归渲染组件时未获取状态

javascript - 去除 HTML 标签内不脏的 HTML 文本 Javascript

javascript - 如何向 Javascript/Jquery slider 添加按钮?

javascript - AngularJs:在使用 ui 路由器时实现了 IIFE

unit-testing - CMake - 在构建过程中运行测试并将标准输出捕获到文件

javascript - 将 <pre> 标签内容复制到 Vue.js 应用程序上的剪贴板

python - 如何在 python3 中的慢速测试中提前失败(例如设置超时)(最好使用nose)

javascript - 避免在 React 中的每个渲染上重新计算变量