react-test-renderer 的 create() 与 @testing-library/react 的 render()

react-test-renderer 的 create() 与 @testing-library/react 的 render()

问题描述:

我是 React 的新手,对所有测试库都感到困惑.我让我的测试代码可以工作,但是为了使用它的 toMatchSnapshot() 并且不得不从 react-test-renderer 调用 create() 并且必须调用它似乎是多余的render() 来自 @testing-library/react 以便使用其断言,例如 getByLabelText().

I'm new to React and confused about all the testing libraries. I got my test code to work but it seems redundant to have to call create() from react-test-renderer in order to use its toMatchSnapshot() and have to call render() from @testing-library/react in order to use its assertions such as 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 库之间的区别.但我想一定有更简单的方法.

As a newbie, it's hard for me to understand the difference between all these React libraries. But I'm thinking there must be a simpler way.

如何简化我的测试代码,以便我只需要调用呈现组件的一件事,以便我可以进行快照测试和更具体的断言?

How can I simplify my test code so I only have to call one thing that renders the component so that I can do snapshot testing and more specific assertions?

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

I got the answer from Ziad Saab at Codementor.io:

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

  • create() allows you test against the virtual DOM (i.e. the "React DOM")

render() 来自 react 测试库并渲染您的树,但也允许您拥有所有 get*() 断言.它允许您针对 DOM 进行测试.

render() comes from react testing library and renders your tree but also allows you to have all the get*() assertions. It allows you to test against the DOM.

以下是简化代码的方法:

Here's how the code can be simplified:

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().

Ziad let me know that there was no reason to have act(), it was something to work around a bug in create(). Now that the code doesn't used create() there is no need for act().

因此,我的快照现在包含 class 而不是 className 因为 class 是实际 HTML DOM 中的内容,而 className 相当于 React 的Virtual DOM".

As a result, my snapshot now contains class instead of className because class is what's in the actual HTML DOM whereas className is its equivalent in React's "Virtual DOM".

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

(Before) Snapshot with create() based on React's Virtual DOM:

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

(After) Snapshot with render() 基于 HTML DOM:

(After) Snapshot with render() based on HTML DOM:

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