IT이야기

테스트하는 동안 MemoryRouter를 사용하여 경로로 이동할 수 없음

cyworld 2022. 3. 19. 12:29
반응형

테스트하는 동안 MemoryRouter를 사용하여 경로로 이동할 수 없음

나는 그 예들을 면밀히 따랐지만, MemoryRouter가 농담과 효소를 이용한 테스트로 작업하도록 할 수는 없다.

경로 중 하나로 이동하여 스냅샷에 반영하고 싶다.하므로, 는 MemoryRouterh"를 "/A"로 .<div>A</div>

import React from 'react';
import Enzyme, {mount} from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import {BrowserRouter as Router, MemoryRouter, Route, Switch} from 'react-router-dom';

Enzyme.configure({adapter: new Adapter()});

describe('Routing test', () => {
    let wrapper;

    beforeEach(() => {
        wrapper = mount(
            <MemoryRouter initialEntries={["/A"]}>
                    <div className={"Test"}>This is my Test Component and should not have any test specific code in it
                        <Router>
                            <Switch>
                                <Route path={"/A"}>
                                    <div className={"A"}>A</div>
                                </Route>
                                <Route path={"/B"}>
                                    <div>B</div>
                                </Route>
                            </Switch>
                        </Router>
                    </div>
                </MemoryRouter>
        );
    });
    afterEach(() => {
        wrapper.unmount();
    });

    it('matches snapshot', () => {
        expect(wrapper.find(".Test")).toHaveLength(1); //this ok
        expect(wrapper.find(".A")).toHaveLength(1); //but this is not ok :( It should find  A
    });
});

보는 대신에<div>Test<div>A</div></div>나는 그저 본다<div>Test</div>

참고: 내 예는 한 클래스로 단순화된다.나의 실제 세계 상황은<div>Test...</div>분리성분이다.

  1. 나는 이것에 대한 어떤 증거도 찾을 수 없지만 나는 항상 네가 하나만 사용해야 하는 것보다 더 인상 깊었다.<Router>나무 꼭대기 어딘가에 둥지를 틀면 안 돼
    그래서 내가 직접 소스 코드를 조사해 보았는데, 만약 내가 제대로 알았다면, 이것은 사실이다.이유:

    1. react-routerContext API를 사용하여 소품을 계층 아래로 전달한다.
    2. 대응 문서:

      [...] 가장 가까운 일치 항목에서 현재 컨텍스트 값을 읽음Provider나무 위에서 말이야

    3. <Router>a이다Provider그러나 a는 아니다.Consumer부모에게서 소품을 훔쳐볼 수 없도록 하기 위해<Router>
  2. 사람들이 시험을 옹호할 때, 그들은 필기 시험이 더 시험 가능한 코드로 이어지고 더 시험 가능한 코드는 더 깨끗하다고 언급한다.나는 이것에 대해 논쟁하지 않을 것이다, 나는 단지 주목하지 않을 것이다, 만약 당신이 테스트 가능한 코드를 쓸 수 있다면, 당신은 테스트할 수 없는 코드도 쓸 수 있다.그리고 이것은 사건처럼 보인다.

    그러니까 구체적으로 그렇게 말하지만.

    테스트 특정 코드를 포함하지 않아야 함

    난 그렇게 생각하지만, 너는 아마 사용해서는 안 될 것이다.createMemoryHistory@putinq의 제안대로, 또는 시험 목적으로만 특별히 그리고 시험 목적으로만 코드를 수정할 수 있고 아마도 더 시험적으로 사용할 수 있도록 수정해야 할 것이다.

    다음 작업을 수행할 수 있음:

    1. 이동하다<Router>더 높은심지어 포장도 할 수 있다.<App>이 방법은 가장 간단하고 권장되는 방법이지만, 귀하의 경우에는 적용되지 않을 수 있다.하지만 난 아직도 네가 왜 말을 못 하는지 모르겠어.<div className={"Test"}>안쪽에<Router>그 반대의 경우도 아니다.
    2. 테스트에서 타사 라이브러리를 테스트하면 안 되며 자신의 코드를 테스트해야 하므로 이 코드를 추출할 수 있음
      <Switch>
        <Route path={"/A"}>
          <div className={"A"}>A</div>
        </Route>
        <Route path={"/B"}>
          <div>B</div>
        </Route>
      </Switch>
      
      별도 부품으로 분할하여 별도로 시험한다.
    3. 또는 이 두 가지를 조합하면: put<div className={"Test"}>안쪽에<Router>, 추출물<div className={"Test"}>별도의 구성요소로 작성한다.
      wrapper = mount(
        <MemoryRouter initialEntries={["/A"]}>
          <TestDiv/>
        </MemoryRouter>
      )
      
    4. ㅎㅎcreateMemoryHistory그 자체로 유용한 특징이 될 수 있다.그리고 언젠가 당신은 그것을 사용하는 것을 알게 될 것이다.그런 경우 @aquinq의 대답은 충분할 것이다.
  3. 그러나 코드를 수정할 수 없거나 수정하지 않을 경우.그런 다음 약간의 속임수를 써서 다음과 같은 접근법을 시도할 수 있다.내부에 있는 <라우터> 태그를 사용하여 구성 요소를 테스트하는 방법?

알았어, 알아냈어.

그것은 매우 못생겼지만 당신은 그것을 만들어야 한다.__mocks__디렉토리(프로젝트의 첫 번째 단계에서). __mocks__문서화는 서툴지만 농담인 것 같고, 여기 있는 모든 것은 테스트할 때 실행될 것이며, 여기에서는 특정 외부 라이브러리에 대한 모의 스텁을 추가할 수 있다.

import React from 'react';

const reactRouterDom = require("react-router-dom")
reactRouterDom.BrowserRouter = ({children}) => <div>{children}</div>

module.exports = reactRouterDom

내 시험 파일은 내 질문과 같다.

import React from 'react';
import Enzyme, {mount} from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import {BrowserRouter as Router, MemoryRouter, Route, Switch} from 'react-router-dom';

Enzyme.configure({adapter: new Adapter()});

describe('Routing test', () => {
    let wrapper;

    beforeEach(() => {
        wrapper = mount(
            <MemoryRouter initialEntries={['/A']}>
                    <div className={"Test"}>This is my Test Component and should not have any test specific code in it
                        <Router>
                            <Switch>
                                <Route path={"/A"}>
                                    <div className={"A"}>A</div>
                                </Route>
                                <Route path={"/B"}>
                                    <div>B</div>
                                </Route>
                            </Switch>
                        </Router>
                    </div>
                </MemoryRouter>
        );
    });
    afterEach(() => {
        wrapper.unmount();
    });

    it('matches snapshot', () => {
        expect(wrapper.find(".Test")).toHaveLength(1); //this ok
        expect(wrapper.find(".A")).toHaveLength(1); //but this is not ok :( It should find  A
    });
});

이것은 효과가 있고 내 시험은 초록색이야! :)

업데이트:

라우터를 다른 반응 구성 요소처럼 취급하고 있었는데, 실제로는 Redex와 같은 최상위 구성 요소인 것 같아.Provider라우터가 안에 있으면 안 된다.App하지만 바깥에App이와 같이(예: 인덱스.js 파일에서).

ReactDOM.render(
    <Provider store={store}>
        <Router>
            <App/>,
        </Router>
    </Provider>,
    document.getElementById('root')
);

이제 앱에 대한 테스트를 쓸 때, 나는 메모리라우터 같은 나만의 라우터를 제공한다.

설명서에 따르면, 정규 분포를 사용하는 경우Router당신의 시험에서 당신은 a를 통과해야 한다.history그것을 떠받치다.

라우터 컨텍스트를 직접 스텁아웃하고 싶을 수도 있지만, 라우터 구성 요소 중 하나인 base에서 장치 테스트를 마무리하는 것이 좋다.Router역사 소품이나, 또는<StaticRouter> <MemoryRouter>또는<BrowserRouter>

이게 효과가 있길 바래.만약 그렇지 않다면, 아마 1초를 사용했을 것이다.MemoryRouter대신에Router그냥 그 일을 할 수 있을 것이다.

일반적으로 라우터는 앱 로직 외부에 있으며 다른 라우터를 사용하는 경우<Route>꼬리표 같은 걸 쓰면 되잖아<Switch>, 다음과 같은 경우:

  <Router>
    <Switch>
      <Route exact path="/">
        <HomePage />
      </Route>
      <Route path="/blog">
        <BlogPost />
      </Route>
    </Switch>
  </Router>

MemoryRouter 사실 그것은 a이기 때문에 여기서 "실제"를 대체하는 것이 가장 좋을지도 모른다.테스트가 용이하도록 별도의 구성 요소로 분리할 수 있다.

GitHub의 출처에 따르면:

로우 레벨 사용을 위한 가장 일반적인 사용 사례<Router>사용자 지정 기록을 Redex 또는 Mobx와 같은 상태 관리 lib와 동기화하는 것이다.이것은 React Router와 함께 상태 관리 libs를 사용할 필요가 없으며, 이는 심층 통합만을 위한 것이라는 점에 유의하십시오.

import React from "react";
import ReactDOM from "react-dom";
import { Router } from "react-router";
import { createBrowserHistory } from "history";

const history = createBrowserHistory();

ReactDOM.render(
  <Router history={history}>
    <App />
  </Router>,
  node
);

개인적 경험으로부터:

나는 (우리는 그것을 "루트"라고 부른다)를 포함하는 외부 컴포넌트를 사용해왔다.<Provider>그리고<Router>상위 레벨의 구성 요소, 그 다음<App>을 포함하다<Switch>그리고<Route>구성 요소들

Root.jsx반환:

<Provider store={rootStore}>
  <Router history={rootHistory}>
    <App />
  </Router>
</Provider>

그리고App.jsx반환:

<Switch>
  <Route exact path="/" component={HomePage}>
  <Route exact path="/admin" component={AdminPage}>
</Switch>

이것은 다음을 허용된다.App.test.jsx사용할 항목:

mount(
  <Provider store={fakeStore}>
    <MemoryRouter initialEntries={['/']}>
      <App myProp={dummyProp} />
    </MemoryRouter>
  </Provider>
)

참조URL: https://stackoverflow.com/questions/62266127/cannot-navigate-to-path-using-memoryrouter-while-testing

반응형