【问题标题】:Can I manually trigger a state change when testing using react-testing-library?使用 react-testing-library 进行测试时,我可以手动触发状态更改吗?
【发布时间】:2019-07-17 03:55:19
【问题描述】:

我仍在将我的 Enzyme 测试转移到 react-testing-library 的过程中,并且我有一个相当常见的场景,当组件安装时,它会启动 Ajax 请求以获取一些数据。就在 fetch 开始之前,它设置了一些状态值来指示它正在加载,这反过来又呈现了一个微调器。完成后,状态将同时更新数据,并且“loadingState”在适当的情况下设置为“Completed”或“Failed”。

import React, { useEffect, useState } from "react";
import { SwapSpinner } from "react-spinners-kit";
import styled from "styled-components";
import * as R from "ramda";

import { getPeople } from "./getPeople";

const FlexCenter = styled.div`
  height: 250px;
  display: flex;
  justify-content: center;
  align-items: center;
`;

const loadingStates = {
  notStarted: "notStarted",
  isLoading: "isLoading",
  success: "success",
  failure: "failure"
};

function App() {
  const [people, setPeople] = useState([]);
  const [isLoading, setLoading] = useState(loadingStates.notStarted);

  useEffect(() => {
    setLoading(loadingStates.isLoading);
    getPeople()
      .then(({ results }) => {
        setPeople(results);
        setLoading(loadingStates.success);
      })
      .catch(error => {
        setLoading(loadingStates.failure);
      });
  }, []);

  return (
    <div>
      {R.cond([
        [
          R.equals(loadingStates.isLoading),
          () => (
            <FlexCenter data-testid="spinner">
              <SwapSpinner />
            </FlexCenter>
          )
        ],
        [
          R.equals(loadingStates.success),
          () => (
            <ul data-testid="people-list">
              {people.map(({ name }) => (
                <li key={name}>{name}</li>
              ))}
            </ul>
          )
        ],
        [R.equals(loadingStates.failure), <div>An error occured</div>]
      ])(isLoading)}
    </div>
  );
}

export default App;

使用 Enzyme,我可以手动将状态设置为任一 loadingStates 键,并断言渲染条件会渲染适当的更改。

有没有办法在 RTL 中做到这一点?

【问题讨论】:

    标签: reactjs jestjs react-testing-library


    【解决方案1】:

    你不能用 RTL 做到这一点。您不应该与组件的内部交互。

    这大概是我测试你的组件的方式:

    import { getPeople } from "./getPeople";
    jest.mock('./getPeople')
    
    test('skeleton of a test', async () => {
      const people = [/* Put some mock people in here */]
      getPeople.mockResolvedValueOnce({ results: people })
      render(<App />)
    
      expect(/* Somehow get the loading spinner */).toBeInTheDocument()
    
      await wait(() => expect(/* Here you check that the people is on the page */).toBeInTheDocument())
    
      // We also check that the API gets called
      expect(getPeople).toHaveBeenCalledOnce()
      expect(getPeople).toHaveBeenCalledWith()
    })
    

    如您所见,我没有检查App 的内部状态。相反,我正在检查是否显示了加载微调器,然后人们会出现在屏幕上并且 API 是否被调用。

    此测试更可靠,因为您测试的是用户将看到的内容,而不是实现细节。

    【讨论】:

      猜你喜欢
      • 2019-05-21
      • 2019-11-11
      • 2019-07-08
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      • 2019-06-03
      • 2019-08-29
      • 2021-11-30
      相关资源
      最近更新 更多