농담, 효소:불변 위반:또는 Router()를 외부 에서 사용하여서는 안 됩니다.
나는 가지고 있다<UserListComponent />
1을 출력<Contact />
컴포넌트 및 연락처 목록<Contacts />
.
문제는 다음 테스트에서<UserListComponent />
마운트하려고 하면 테스트가 오류를 출력합니다.Invariant Violation: You should not use <Route> or withRouter() outside a <Router>
withRouter()
에 사용됩니다.<Contacts />
요소.
어떻게 조롱할 수 있지?ContactsComponent
부모 컴포넌트 테스트에서 라우터를 사용하지 않는 경우
비슷한 이슈 https://www.bountysource.com/issues/49297944-invariant-violation-you-should-not-use-route-or-withrouter-outside-a-router을 찾았는데 컴포넌트가 커버되는 상황만 기재되어 있습니다.withRouter()
아이가 아니라 그 자체입니다.
UserList.test.jsx
const mockResp = {
count: 2,
items: [
{
_id: 1,
name: 'User1',
email: 'email1@gmail.com',
phone: '+123456',
online: false
},
{
_id: 2,
name: 'User2',
email: 'email2@gmail.com',
phone: '+789123',
online: false
},
{
_id: 3,
name: 'User3',
email: 'email3@gmail.com',
phone: '+258369147',
online: false
}
],
next: null
}
describe('UserList', () => {
beforeEach(() => {
fetch.resetMocks()
});
test('should output list of users', () => {
fetch.mockResponseOnce(JSON.stringify(mockResp));
const wrapper = mount(<UserListComponent user={mockResp.items[2]} />);
expect(wrapper.find('.contact_small')).to.have.length(3);
});
})
UserList.jsx
export class UserListComponent extends PureComponent {
render() {
const { users, error } = this.state;
return (
<React.Fragment>
<Contact
userName={this.props.user.name}
content={this.props.user.phone}
/>
{error ? <p>{error.message}</p> : <Contacts type="contactList" user={this.props.user} contacts={users} />}
</React.Fragment>
);
}
}
Contacts.jsx
class ContactsComponent extends Component {
constructor() {
super();
this.state = {
error: null,
};
}
render() {
return (
<React.Fragment>
<SectionTitle title="Contacts" />
<div className="contacts">
//contacts
</div>
</React.Fragment>
);
}
}
export const Contacts = withRouter(ContactsComponent);
다음을 포함하는 구성 요소를 테스트하려면(Jest 사용)<Route>
그리고.withRouter
컴포넌트가 아닌 테스트에서 라우터를 Import해야 합니다.
import { BrowserRouter as Router } from 'react-router-dom';
이렇게 해서
app = shallow(
<Router>
<App />
</Router>);
마운트를 컨텍스트와 함께 랩하는 유틸리티 기능
테스트에서 라우터를 사용하여 마운트를 래핑하면 작동하지만 마운트의 상위 구성요소가 라우터를 사용하지 않을 수 있습니다.따라서 저는 현재 래퍼 기능을 사용하여 콘텍스트를 마운트에 주입하고 있습니다.
import { BrowserRouter } from 'react-router-dom';
import Enzyme, { shallow, mount } from 'enzyme';
import { shape } from 'prop-types';
// Instantiate router context
const router = {
history: new BrowserRouter().history,
route: {
location: {},
match: {},
},
};
const createContext = () => ({
context: { router },
childContextTypes: { router: shape({}) },
});
export function mountWrap(node) {
return mount(node, createContext());
}
export function shallowWrap(node) {
return shallow(node, createContext());
}
이것은, 예를 들면 contextWrap.js 라고 하는 파일의 테스트 도우미 디렉토리에 있는 경우가 있습니다.
블록 설명 예:
import React from 'react';
import { TableC } from '../../src/tablec';
import { mountWrap, shallowWrap } from '../testhelp/contextWrap';
import { expectedProps } from './mockdata'
describe('Table', () => {
let props;
let component;
const wrappedShallow = () => shallowWrap(<TableC {...props} />);
const wrappedMount = () => mountWrap(<TableC {...props} />);
beforeEach(() => {
props = {
query: {
data: tableData,
refetch: jest.fn(),
},
};
if (component) component.unmount();
});
test('should render with mock data in snapshot', () => {
const wrapper = wrappedShallow();
expect(wrapper).toMatchSnapshot();
});
test('should call a DeepTable with correct props', () => {
const wrapper = wrappedMount();
expect(wrapper.find('DeepTable').props()).toEqual(expectedProps);
});
});
또한 이 패턴을 사용하여 다른 유형의 컨텍스트(react-intl, material-ui 또는 자체 컨텍스트 유형 등)에서 하위 구성요소를 래핑할 수도 있습니다.
포장해야 합니다.App
와 함께BrowserRouter
또는 이와 동등한 것을 사용하는 컴포넌트 App의 간단한 테스트 사례의 예를 참조하십시오.
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import App from "./App";
it("renders without crashing", () => {
const div = document.createElement("div");
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
div
);
ReactDOM.unmountComponentAtNode(div);
})
저도 같은 문제가 있었고, 첫 번째 코멘트가 도움이 되었습니다만, 이 문제를 해결하는 더 나은 방법이 많은 코드가 있습니다.아래 솔루션을 참조하십시오.
import React from 'react';
import { shallow, mount } from 'enzyme';
import SisuSignIn from '../../../components/Sisu/SisuSignIn.js';
import { MemoryRouter } from 'react-router-dom';
const Container = SisuSignIn;
let wrapper;
beforeEach(() => {
wrapper = shallow(<Container />);
});
describe('SisuSignIn', () => {
it('renders correctly', () => {
expect(wrapper).toMatchSnapshot();
});
it('should render one <h1>', () => {
const wrapper = mount(
<MemoryRouter>
<SisuSignIn auth={{ loading: false }} />
</MemoryRouter>
);
expect(wrapper.find('div').length).toBe(12);
});
});
A에서는, 「URL」의 이력을 메모리에 보존합니다(주소 바에의 읽기 또는 쓰기는 행해지지 않습니다).테스트 및 React Native와 같은 브라우저 이외의 환경에서 유용합니다.
메모리 라우터의 도움을 받아 컴포넌트를 래핑하는 유사한 에러 솔루션을 받았습니다.
import { MemoryRouter } from 'react-router'
<MemoryRouter>
<App/>
</MemoryRouter>
렌더링할 라우터 태그를 추가합니다.
import * as React from "react";
import { render, mount } from 'enzyme';
import { BrowserRouter as Router } from "react-router-dom"
import CategoriesToBag from "../CategoriesToBag";
describe('Testing CategoriesToBag Component', () => {
test("check if heading is correct", () => {
const defaultValue = "Amazing Categories To Bag";
const wrapper = render(<Router><CategoriesToBag /></Router>);
expect(wrapper.find('.textBannerTitle').text()).toMatch(/Categories To Bag/);
expect(wrapper.find('.textBannerTitle').text()).not.toMatch(/Wrong Match/);
expect(wrapper.find('.textBannerTitle').text()).toBe(defaultValue);
});
});
당신은 가도 됩니다.
실제로 컴포넌트의 스냅숏 테스트를 작성했습니다.react-test-renderer
그리고 이 문제에 직면했고 제가 한 일은 제 컴포넌트를BrowserRouter
와 함께 출하되는react-router-dom
, 다음과 같이 실행할 수 있습니다.
import React from 'react'
import { BrowserRouter } from 'react-router-dom'
import renderer from "react-test-renderer";
import UserListComponent from './whatever'
test('some description', () => {
const props = { ... }
const jsx = (
<BrowserRouter>
<UserListComponent {...props} />
</BrowserRouter>
)
const tree = renderer.create(jsx).toJSON()
expect(tree).toMatchSnapshot()
})
totaly는 여러 번 테스트하고 싶다면 이러한 상황에서 테스트 팩토리를 사용할 것을 권장합니다.
그래서 저는 오랫동안 이 문제에 대해 생각하고 있었습니다만, 실제로는 withRouter의 실장에 대해서는 신경쓰지 않습니다(다른 곳에서 동작하거나 테스트하는 것으로 가정할 수 있습니다).따라서 그 함수는 스스로 되돌리기 위해 조롱할 수 있습니다(Link 함수에서 했던 것과 거의 같습니다).
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
Link: () => <div />,
withRouter: (x) => x,
}));
몇 시간 전만 해도 도움이 됐을 것 같은 사람에게 도움이 됐으면 좋겠어요!
언급URL : https://stackoverflow.com/questions/50025717/jest-enzyme-invariant-violation-you-should-not-use-route-or-withrouter-ou
'source' 카테고리의 다른 글
Wordpress post_meta에 저장할 때 'SimpleXMLement' 직렬화가 허용되지 않습니다. (0) | 2023.02.09 |
---|---|
SQL 오류: ORA-00942 테이블 또는 뷰가 존재하지 않습니다. (0) | 2023.02.09 |
Angular 5의 URL에서 쿼리 파라미터를 얻는 방법 (0) | 2023.02.09 |
JSON JQ(기타 없는 경우) (0) | 2023.02.09 |
PDO:: fetchAll vs. PDO:: 루프에서의 fetch (0) | 2023.02.01 |