React重定向单元测试未呈现预期的dom

时间:2021-02-15 09:56:47

标签: javascript reactjs unit-testing testing react-testing-library

我正在尝试单元测试(使用 React 测试库)我的重定向是否按预期发生并且在实践中实际发生,但是我的测试中似乎没有实际呈现任何内容...


App.js

// I set up a test route to get this working before I point it at the real page

<Route exact path={`${process.env.PUBLIC_URL}/blah`} render={() => (
    <div data-testid="my-test">THIS IS A TEST</div>
)}/>

MyComponent.jsx

// I have forced this component to do the redirect for testing purposes
...
return (
    <BrowserRouter>
        <Redirect to={`${process.env.PUBLIC_URL}/blah`} />
    </BrowserRouter>
);

我发现不将我的 <Redirect> 包裹在 <BrowserRouter> 中会产生错误

You should not use <Redirect> outside a <Router>

Test.js

it('should redirect', async () => {
    const state = configState(); // <---- Set custom initial state of component
    const store = configureStore();

    rendered = render(
        <Provider store={store(state)}>
            <ForgotPasswordNewPasswordJourney />
        </Provider>
    );

    // check that the content changed to the new page
    expect(rendered.getByText("THIS IS A TEST")).toBeTruthy();
});

这个测试的结果是:

TestingLibraryElementError: Unable to find an element with the text: THIS IS A TEST. 
This could be because the text is broken up by multiple elements. 
In this case, you can provide a function for your text matcher to make your matcher more flexible.

<body>
   <div />
   <div />
</body>

      116 | 
      117 |         // check that the content changed to the new page
    > 118 |         expect(rendered.getByText("THIS IS A TEST")).toBeTruthy();
          |                         ^
      119 |     });
      120 | 
      121 | 

注意:当我也用 <BrowserRouter> 包装测试渲染时,我也会收到此错误:

<Provider store={store(state)}>
    <BrowserRouter>
         <ForgotPasswordNewPasswordJourney />
    </BrowserRouter>
</Provider>

特殊行为... 我确实在网上读到可能是 async/await 问题,因为重定向需要时间来执行等。所以我看到使用 waitFor 可能是一种选择,并且在执行时:

waitFor(() => expect(rendered.getByText("THIS IS A TEST")).toBeTruthy());

这实际上让我惊讶地通过了测试......但是,如果我在 getByText 字段中放入一个无意义的字符串,这也将通过我的测试......所以看起来这也不是答案。

我做错了什么?

1 个答案:

答案 0 :(得分:0)

我在查看 this article 后设法解决了这个问题,我可以看到我的错误。

看来我需要在我的 <Router 中添加一个 <Route<Provider> 作为一种模拟路线。

const myStore = configureStore();
const history = createMemoryHistory();
history.push(fromUrl);

<Provider store={myStore(store)}>
   <Router history={myHistory}>
       <Component {...props} />
       <Route path={toUrl}>
           <div data-testid="test">THIS IS A TEST</div>
       </Route>
   </Router>
</Provider>

然后我可以开始看到测试中呈现的东西。

也可以实际渲染一个组件而不是一个测试元素:

<Route path={toUrl}> render={() => <RedirectComponent {...props} />}

但是,如果这是使用 Redux,我们将需要添加 <Provider> 并围绕它存储包装器。