如何测试子组件是否已呈现?

ris*_*os3 27 reactjs jestjs react-testing-library

在酶中,您可以像这样检查子组件的存在:

expect(wrapper.find(ChildComponent)).toHaveLength(1)
Run Code Online (Sandbox Code Playgroud)

反应测试库中的这个测试相当于什么?我发现的所有在线示例都只涵盖了寻找 dom 元素的非常简单的测试——没有一个包含渲染子组件的示例。你如何找到一个子组件?

Nol*_*esh 10

您可以使用@testing-library/jest-dom库。

成分:

<div role="root">       
    <div data-testid="parent">
        <div data-testid="child">
            content
        </div>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

测试:

import '@testing-library/jest-dom'
import {render} from '@testing-library/react';

describe('My component', () => {
    test('should render component2', () => {
        const { getByRole, getByTestId } = render(<Component/>);

        const root = getByRole('root');
        const parent = getByTestId('parent');
        const child = getByTestId('child');

        expect(root).toContainElement(parent);
        expect(parent).toContainElement(child);
        
        expect(child).not.toContainElement(parent); // Pass
        expect(child).toContainElement(parent); // Throw error!    
    });
});
Run Code Online (Sandbox Code Playgroud)

另一个解决方案是使用库within中的函数@testing-library/react

import { within } from '@testing-library/react';
...

expect(within(parent).queryByTestId('child')).not.toBeNull();
Run Code Online (Sandbox Code Playgroud)


Ami*_*han 9

你不应该检查你的子组件是否被渲染,因为它正在测试实现细节(哪个测试库不鼓励你这样做)。

您可以检查子组件中的一些文本是否已呈现,或者您可以将 data-testid 提供给 child 中的包装元素,然后使用来自 @testing-library/jest-dom 的 .toBeInTheDocument

expect(getByText(/some text/i)).toBeInTheDocument();
Run Code Online (Sandbox Code Playgroud)

或者

expect(getByTestId('your-test-id')).toBeInTheDocument();
Run Code Online (Sandbox Code Playgroud)

更新:示例

// Child Component
function ChildComponent() {
    return <div>Child Element</div>;
};

// Parent
export default function Parent() {
    return (
        <div className="App">
            <ChildComponent />
        </div>
    );
}
Run Code Online (Sandbox Code Playgroud)

测试:

import { render } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";
import Parent from "./App";

test("test child component", () => {
  const { getByText } = render(<Parent />);
  expect(getByText(/child element/i)).toBeInTheDocument();
});
Run Code Online (Sandbox Code Playgroud)

  • @AmitChauhan 有些组件没有文本。例如,像旋转器一样。 (5认同)
  • 但是,如果我通过组件显示的文本进行测试,则每次更改组件文本时,我都需要更新组件测试以及使用该组件的所有其他组件 (4认同)
  • 我可以获得完整的测试样本吗? (2认同)
  • `你不应该检查你的子组件是否被渲染,因为它正在测试实现细节` - 这根本不是真的。例如,我想检查父组件在获取数据时是否显示微调器。这不是实现细节,除非我寻找特定的微调器类等。 (2认同)

Mik*_*cer 9

我为此目的使用了React Test Renderer :

import TestRenderer from 'react-test-renderer';

import ItemList from 'components/ItemList';
import LoadingIndicator from 'components/LoadingIndicator';

test('renders loading indication', () => {
    const testRenderer = TestRenderer.create(
        <ItemList items={[]} isLoading={true}/>
    );
    const testInstance = testRenderer.root;
    testInstance.findByType(LoadingIndicator);
});
Run Code Online (Sandbox Code Playgroud)

我不认为这是“测试实现细节”,恰恰相反 - LoadingIndicator 组件可以修改而无需修复测试用例。


小智 8

我同意每个人的说法,检查子组件内的文本或测试 ID 就是测试实现细节。

但是我们可以使用模拟来摆脱子组件的实现细节。

要测试的代码:

import { ChildComponent } from 'child-from-somewhere';

export function Parent() {
    return (
        <div className="App">
            <ChildComponent />
        </div>
    );
}
Run Code Online (Sandbox Code Playgroud)

检查 ChildComponent 是否已呈现的测试代码:

import { render } from "@testing-library/react";
import React from "react";
import { Parent } from "./parent";

jest.mock("child-from-somewhere", () => ({
    ChildComponent: () => <div data-testid="ChildComponent">ChildComponent</div>,
}));

describe("ChildComponent component", () => {
    it("should be in the document", () => {
        const { getByTestId } = render(<Parent />);
        expect(getByTestId("ChildComponent")).toBeInTheDocument();
    });
});

Run Code Online (Sandbox Code Playgroud)

这样,测试就可以独立于ChildComponent.


sky*_*yer 4

因为如果找不到元素则query*返回,您可能只是null

expect(queryByTestId('test-id-you-provided')).toEqual(null);
expect(queryByTestId('some-other-test-id-you-provided')).not.toEqual(null);
Run Code Online (Sandbox Code Playgroud)

getBy*如果找不到元素也会抛出异常。所以下一个应该也可以工作

getByTestId('test-id-you-provided'); 
Run Code Online (Sandbox Code Playgroud)