React 测试库不变量失败:您不应该在 <Router> 之外使用 <Route>
Posted
技术标签:
【中文标题】React 测试库不变量失败:您不应该在 <Router> 之外使用 <Route>【英文标题】:React Testing Library Invariant failed: You should not use <Route> outside a <Router> 【发布时间】:2020-12-10 07:11:03 【问题描述】:我正在测试我的组件是否使用 React 测试库成功使用 Redux 呈现。我无法让我的实用程序组件通过 renderWithRedux 测试。这是我的 App 组件。
function App()
return (
<>
<Router>
<NavBar />
<div className="container">
<Switch>
<Route exact path='/' component=Home/>
<AuthRoute exact path='/login' component=Login />
<AuthRoute exact path='/signup' component=Signup />
<Route exact path='/users/:handle' component=UserProfile />
<Route exact path='/users/:handle/post/:postId' component=UserProfile />
</Switch>
</div>
</Router>
</>
);
这是我的 AuthRoute 实用程序组件。
const AuthRoute = ( component: Component, authenticated, ...rest ) => (
// if authenticated, redirect to homepage, otherwise redirect to signup or login
<Route
...rest
render=(props) =>
authenticated === true ? <Redirect to='/' /> : <Component ...props />
/>
);
AuthRoute.test.js
const renderWithRedux = () => render(
<Provider store=myStore>
<AuthRoute />
</Provider>
);
it('renders with Redux', () =>
const = renderWithRedux(<AuthRoute />);
);
我尝试了Invariant failed: You should not use <Route> outside a <Router> 的解决方案,但无济于事。感谢您的帮助,谢谢。
【问题讨论】:
【参考方案1】:将被测组件渲染到路由器中
import MemoryRouter from 'react-router-dom';
const renderWithRedux = ( children ) => render(
<Provider store=myStore>
children
</Provider>
);
it('renders with Redux', () =>
const = renderWithRedux(
<MemoryRouter>
<AuthRoute />
</MemoryRouter>
);
);
【讨论】:
谢谢,但我收到了Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.
@kennjamin 在您的renderWithRedux
中您是否真的打算在测试中包装传递给它的任何组件(即渲染传递给它的子组件)?我更新了我的答案。
成功了!你是对的,我应该改变包装 App
组件,而不是用孩子包装。谢谢!【参考方案2】:
就像 Provider
包装 redux 的东西一样,您必须使用 MemoryRouter
的路由包装您的组件以进行测试。
import MemoryRouter from 'react-router';
【讨论】:
谢谢,但我收到了Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.
【参考方案3】:
基本上,您有两个包装器元素。它应该是这样的,例如,renderWithReduxWrapp => renderWithRouter => YourTestingComponent。
我在尝试根据 props 测试 Button 渲染(有一个链接)时遇到了类似的问题,并且能够通过创建一些辅助函数来解决它。
示例如下:
这是主要组件,UserCard.js
,它从redux渲染用户数据,并且只有在传递withButton
props时才会显示一个按钮。
import React from "react";
import Link from "react-router-dom";
import Button from "react-bootstrap";
const CardComponent = ( withButton ) =>
const userInfo = useSelector((state) => getUserSelector(state));
return (
<div>
<div>userInfo</div>
withButton && (
<Link to="/settings" className="button-link">
<Button block>EDIT CONTACT INFO</Button>
</Link>
)
</div>
);
;
export default CardComponent;
这是一个 CardComponent.test.js
文件。
首先,你需要添加这几行代码
const ReduxWrapper = ( children ) =>
<Provider store=store>children </Provider>;
const AppWrapper = ( children ) => (
<BrowserRouter>
<ReduxWrapper>children</ReduxWrapper>
</BrowserRouter>
);
const renderWithRouter = (ui, route = '/' = ) =>
window.history.pushState(, 'Test page', route);
return render(ui, wrapper: AppWrapper );
;
之后,您需要使用 renderWithRouter
而不仅仅是 render
方法开始测试。
it('should render settings button if prop withButton is passed', () =>
renderWithRouter(<CardComponent withButton />, wrapper: ReduxWrapper );
// apply you code here. I only needed to check if the button is renederd or not.
const settingsButton = screen.queryByText(/edit contact info/i);
expect(settingsButton).toBeInTheDocument();
);
【讨论】:
以上是关于React 测试库不变量失败:您不应该在 <Router> 之外使用 <Route>的主要内容,如果未能解决你的问题,请参考以下文章
不变式失败:您不应该在 <Router> 之外使用 <Link>
开玩笑 - 不变式失败:您不应该在 <Router> 之外使用 <Link>
使用 Enzyme 测试 React 组件时出错:'不变违规:您不应在 <Router> 外使用 <Link>'