【问题标题】:How do I test that a child component is rendered?如何测试子组件是否已呈现?
【发布时间】:2020-05-19 08:11:35
【问题描述】:

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

expect(wrapper.find(ChildComponent)).toHaveLength(1)

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

【问题讨论】:

  • 可能是expect(wrapper).toContain('ChildComponent')?

标签: reactjs jestjs react-testing-library


【解决方案1】:

因为query*返回null如果没有找到元素你可能只是

expect(queryByTestId('test-id-you-provided')).toEqual(null);
expect(queryByTestId('some-other-test-id-you-provided')).not.toEqual(null);

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

getByTestId('test-id-you-provided'); 

【讨论】:

    【解决方案2】:

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

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

    expect(getByText(/some text/i)).toBeInTheDocument();
    

    expect(getByTestId('your-test-id')).toBeInTheDocument();
    

    更新:示例

    // Child Component
    function ChildComponent() {
        return <div>Child Element</div>;
    };
    
    // Parent
    export default function Parent() {
        return (
            <div className="App">
                <ChildComponent />
            </div>
        );
    }
    

    测试:

    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();
    });
    

    【讨论】:

    • 我可以获得完整的测试样本吗?
    • 你不希望括号是这样的:expect(getByText(/some text/i)).toBeInTheDocument();
    • @ninjastar 感谢您指出这一点。更新答案。
    • @NkoroJosephAhamefula 这完全取决于您的用例。这只是一个如何测试子组件是否被渲染的例子。这个周末我会尝试创建一个简单的例子。
    • You shouldn't check if your child component is rendered or not, because it's testing implementation details - 这根本不是真的。例如,我想检查父组件在获取数据时是否显示微调器。这不是实现细节,除非我寻找特定的微调器类等。
    【解决方案3】:

    我为此使用了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);
    });
    

    我不认为它是“测试实现细节”,恰恰相反——LoadingIndicator 组件可以在不需要修复测试用例的情况下进行修改。

    【讨论】:

    • 感谢@Mikhail Batcer 控制预期行为的一种更好的做法是expect(() =&gt; root.findByType(WichedComponent)).not.toThrow()
    【解决方案4】:

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

    组件:

    <div role="root">       
        <div data-testid="parent">
            <div data-testid="child">
                content
            </div>
        </div>
    </div>
    

    测试:

    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!    
        });
    });
    

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

    import { within } from '@testing-library/react';
    ...
    
    expect(within(parent).queryByTestId('child')).not.toBeNull();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-24
      • 1970-01-01
      • 2018-04-25
      • 1970-01-01
      • 2020-03-23
      • 1970-01-01
      • 2020-06-28
      相关资源
      最近更新 更多