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

Posted

技术标签:

【中文标题】如何测试子组件是不是已呈现?【英文标题】: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')? 【参考方案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();

【讨论】:

以上是关于如何测试子组件是不是已呈现?的主要内容,如果未能解决你的问题,请参考以下文章

使用 react-testing-library 时如何测试组件是不是使用正确的道具呈现?

如何有条件地测试样式化的组件和子元素?

测试按钮单击 ReactJS 上是不是呈现另一个组件

ReactJs:如何创建一个包装器组件,该组件在单击时会执行某些代码并呈现子组件?

如何在(子)组件上使用 Axios 调用 API 并将结果呈现在 Nuxt 中的 Page(父)组件上?

如何使用Vue.js获取呈现dom元素的组件