使用 Jest 和 Enzyme 测试 react-router 重定向

Posted

技术标签:

【中文标题】使用 Jest 和 Enzyme 测试 react-router 重定向【英文标题】:Testing react-router Redirects with Jest and Enzyme 【发布时间】:2019-02-20 11:21:08 【问题描述】:

我有一个使用 react-router 的简单 React 组件,如果用户无权查看某个路由,它会重定向用户:

class App extends Component 
  constructor(props) 
    super(props);
    this.state = permission: false;
  

  render() 
    return (
      <Switch>
        <Route exact path="/users">
          <h2>A list of users</h2>
        </Route>
        <Route path="/users/:userId">
          (match) => this.state.permission ? <h1>match.params.userId</h1> : <Redirect to="/users" />
        </Route>
      </Switch>
    );
  

我正在尝试使用 Jest 和 Enzyme 访问 /users/:userId 时测试不同的场景,但是当用户获得许可时,我无法让测试成功。

我的测试如下:

describe("render()", () => 
  describe("when route is /users/:userId", () => 
    let wrapper;
    let app;
    beforeEach(() => 
      wrapper = mount(
        <MemoryRouter initialEntries=["/users/1"]>
          <App />
        </MemoryRouter>
      );
      app = wrapper.find(App).instance();
    );

    describe("when user has permission", () => 
      beforeEach(() => 
        app.setState(permission: true);
      );

      it("should show users id", () => 
        expect(wrapper.exists("h1")).toBe(true);
      );
    );

    describe("when user doesn't have permission", () => 
      beforeEach(() => 
        app.setState(permission: false);
      );

      it("should redirect to users list", () => 
        expect(wrapper.exists("h2")).toBe(true);
      );
    );
  );
);

第一次测试失败,第二次成功。我在第一个测试中使用了console.log(wrapper.debug());,它显示该组件正在呈现第一条路由(即被重定向)并且我已经打印出状态,所以我可以看到setState 调用正在工作。

我应该如何重写我的测试来完成这项工作?

【问题讨论】:

【参考方案1】:

问题

初始位置设置为/users/1,但当组件首次挂载时,它会呈现Redirect,将位置设置为/users

然后将permission 设置为true,但由于位置为/users,因此结果为&lt;h2&gt;A list of users&lt;/h2&gt;


解决方案

permission设置为true后,将位置设置为/users/1,这样位置正确,测试成功渲染&lt;h1&gt;1&lt;/h1&gt;

describe("render()", () => 
  describe("when route is /users/:userId", () => 
    let wrapper;
    let app;
    beforeEach(() => 
      wrapper = mount(
        <MemoryRouter initialEntries=["/users/1"]>
          <App />
        </MemoryRouter>
      ); // the Redirect sets location to /users during the initial render
      app = wrapper.find(App).instance();
    );

    describe("when user has permission", () => 
      beforeEach(() => 
        app.setState(permission: true);
        wrapper.instance().history.replace('/users/1'); // replace the MemoryRouter location with /users/1
        wrapper.update(); // update the wrapper with the changes
      );

      it("should show users id", () => 
        expect(wrapper.exists("h1")).toBe(true); // SUCCESS
      );
    );

    describe("when user doesn't have permission", () => 
      beforeEach(() => 
        app.setState(permission: false);
      );

      it("should redirect to users list", () => 
        expect(wrapper.exists("h2")).toBe(true);
      );
    );
  );
);

【讨论】:

以上是关于使用 Jest 和 Enzyme 测试 react-router 重定向的主要内容,如果未能解决你的问题,请参考以下文章

使用 React Suspense 和 React.lazy 子组件进行 Jest/Enzyme 类组件测试

使用 Jest 和 Enzyme 测试 react-router 重定向

异步 componentDidMount 时使用 React 的 Jest 和 Enzyme 进行测试

React / Enzyme:运行 Jest / Enzyme 测试时出现 Invariant Violation 错误

使用 Jest / Enzyme 在 React 中的功能组件内部测试方法

Jest 和 Enzyme 的问题