react-test-renderer的create()与@testing-library/react的render()有何不同?

27

我是React的新手,对所有的测试库感到困惑。虽然我的测试代码可以工作,但似乎需要调用react-test-renderer中的create()才能使用其toMatchSnapshot(),并且需要调用@testing-library/react中的render()才能使用其断言函数,如getByLabelText(),这似乎有些重复。

import {render} from '@testing-library/react';
import {act, create} from 'react-test-renderer';

it('renders a login screen', () => {
    let mockInitialState: AppState = {
        auth: initialAuthState
    };

    let component = <Root initialState={mockInitialState}/>;

    let tree = null;
    act(() => {
        tree = create(component);
    });
    expect(tree).toMatchSnapshot();

    const {getByLabelText, getByText} = render(component);
    expect(getByLabelText(/Email Address.*/));
    expect(getByLabelText(/Password*/));
    expect(getByText('Sign in'));
});
作为新手,我很难理解所有这些React库之间的区别。但是我在想一定有一种更简单的方法。
如何简化我的测试代码,以便我只需调用一个渲染组件的函数,以便进行快照测试和更具体的断言?
2个回答

15

我从Codementor.io的Ziad Saab那里得到了答案:

  • create()允许您针对虚拟DOM(即“React DOM”)进行测试。

  • render()来自react testing library,它呈现您的树形结构,同时允许您进行所有get*()断言。它允许您针对DOM进行测试。

以下是代码简化的方法:

it('renders a login screen', () => {
    let mockInitialState: AppState = {
        auth: initialAuthState
    };

    const {container, getByLabelText, getByText} = render(<Root initialState={mockInitialState}/>);
    expect(container.firstChild).toMatchSnapshot();
    expect(getByLabelText(/Email Address.*/));
    expect(getByLabelText(/Password*/));
    expect(getByText('Sign in'));
});

Ziad让我知道,没有必要使用act(),它是为了解决create()中的漏洞而设计的。现在代码不再使用create(),因此也不需要act()

因此,我的快照现在包含class而不是className,因为class是实际HTML DOM中的内容,而className是React的“虚拟DOM”中的等效内容。

(之前)基于React虚拟DOM的create()快照:

className="MuiBox-root MuiBox-root-256"

基于 HTML DOM 的 render() 快照:

class="MuiBox-root MuiBox-root-256"

2
测试时使用 DOM 而非 Virtual DOM 有什么好处吗?在哪些情况下应考虑使用 Virtual DOM 进行测试? - mehul9595
2
通常我更喜欢测试虚拟DOM,只有在虚拟DOM无法验证某些关键需求时才测试实际DOM。例如,如果客户报告了特定浏览器上的错误,并且我无法通过虚拟DOM重现该错误,则会针对DOM编写测试。 - Michael Osofsky
1
我注意到DOM事件,例如onClick在通过HTML DOM渲染时被剥离了?因此使用虚拟DOM进行快照可能是一个好主意。 - zanona

3
如果您正在使用Create React App,则建议使用react-testing-library,因为它已经包含在其中。
除了container之外,您还可以使用asFragment进行快照测试。
 const { asFragment } = render(<Root initialState={mockInitialState}/>);
 expect(asFragment()).toMatchSnapshot();


container从未被使用,而asFragment似乎未定义。你的意思是要解构asFragment而不是container吗?此外,使用asFragment有什么优势呢?谢谢! - ggorlen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接