【问题标题】:How to test the child component render text after the button on the parent component click with react testing library?如何在使用反应测试库单击父组件上的按钮后测试子组件呈现文本?
【发布时间】:2021-05-13 07:07:56
【问题描述】:

我有一个父组件App,它有一个按钮。单击按钮时,它将调用axios 获取帖子,然后渲染帖子项目。 App 有一个子组件 PostPost 有一个子组件 ListItem。在我的 App 测试文件中,我测试了 axios 在单击按钮后可以正确加载。但是,我无法测试呈现的内容。找不到data-testid:Unable to find an element by: [data-testid="test-axios-content"]

我使用react testing library

这是我的测试文件:

import React from "react"
import App from "../../App"
import { render, fireEvent, screen, waitFor, act } from "../utils/test-utils"
import axios from "axios"

jest.mock("axios", () => {
    return {
        get: jest.fn()
    }
})

describe("App test", () => {
    afterEach(() => {
        jest.resetAllMocks()
    })
    it("should load and display the data", async () => {
        const { getByTestId } = render(<App />)

        axios.get.mockResolvedValueOnce({
            data: { title: "hello there", body: "abc" }
        })
        await act(async () => {
            fireEvent.click(getByTestId("test-axios-button"))
            expect(axios.get).toHaveBeenCalledTimes(1)
            const testingData = await waitFor(() => getByTestId("test-axios-content"))
            expect(testingData).toHaveTextContent("hello there")
        })
    })
})

第一个 axios 调用时间是正确的,但是我的测试找不到 testId test-axios-content。我把它放在 App.js 上的子组件上。

App.js

...
function App() {
    const [posts, setPosts] = useState([])
    const handleClick= async () => {
        const postsResult = await getPosts()
        setPosts(postsResult.data)
    }
    return (
        <div className="App" data-test="appComponent">
            <button data-testid="test-axios-button" onClick={handleClick}>
                get post from axios
            </button>
            <section>
                <div>Load Posts:</div>
                <Post posts={posts} data-testid="test-axios-content" />
            </section>
        </div>
}
...

api 获取帖子:

import axios from "axios"
export const getPosts = async () => await axios.get("https://jsonplaceholder.typicode.com/posts?_limit=10")

帖子:

import ListItem from "../listItem"

const Post= (props) => {
    const posts = props.posts
    return (
        <>
            {posts.length > 0 && (
                <div>
                    {posts.map((post, index) => {
                        const { title, body } = post
                        return <ListItem key={title} title={title} desc={body} />
                    })}
                </div>
            )}
        </>
    )
}

export default Post

列表项:

const ListItem = (props) => {
    const { title, desc } = props
    return (
        <div>
            <h2 data-test="title" data-testid="title">
                {title}
            </h2>
            <div data-test="desc" data-testid="desc">
                {desc}
            </div>
        </div>
    )
}

export default ListItem

【问题讨论】:

  • 只是对单元测试方法的评论...您有 3 个组件,并且您正在测试顶部组件的后代组件...这更像是一个集成测试而不是一个单元测试。也许从对ListItem 的单元测试开始,它呈现通过的desctitle 道具,然后对Post 进行单元测试,其中ListItem 被模拟,等等......你的单元测试真的不应该一次接触多个代码单元。当你进行单元测试App 时,你就知道它下面的所有代码都已经过测试了。
  • 是的,我已经对子组件进行了单元测试。

标签: reactjs axios react-testing-library


【解决方案1】:

第一个错误的部分是posts 是一个数组,但在axios mock 上,它是一个对象:{ title: "hello there", body: "abc" }。正确的格式是:[{ title: "hello there", body: "abc" }]

所以,在测试的axios mock 部分,正确的代码是:

axios.get.mockResolvedValueOnce({
    data: [{ title: "hello there", body: "abc" }]
})

第二个错误的部分是而不是使用await act,它应该先使用触发点击,然后使用await waitFor和回调:

fireEvent.click(getByTestId("test-axios-button"))
await waitFor(() => {
    expect(axios.get).toHaveBeenCalledTimes(1)
    const renderData = screen.getByText("hello there")
    expect(renderData).toBeInTheDocument()
})

这是决赛:

it("should load and display the data", async () => {
    const { getByTestId } = render(<App />)

    axios.get.mockResolvedValueOnce({
        data: [{ title: "hello there", body: "abc" }]
    })
    fireEvent.click(getByTestId("test-axios-button"))
    await waitFor(() => {
        expect(axios.get).toHaveBeenCalledTimes(1)
        const testingData = await waitFor(() => getByTestId("test-axios-content"))
        expect(testingData).toHaveTextContent("hello there")
    })
})

【讨论】:

    猜你喜欢
    • 2021-06-23
    • 2020-09-28
    • 2020-03-26
    • 1970-01-01
    • 1970-01-01
    • 2019-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多