React Testing库清理在Jest的describe bocks中不起作用

时间:2019-07-18 15:30:02

标签: jestjs react-testing-library

我有一些正在进行的测试,正在按预期进行:

describe('Parent', () => {
    afterEach(() => {
        cleanup();
        jest.resetModules();
    });

    describe('Test 1', () => {
        const wrapper = render(
            <MockProvider>
                <MyComponent />
            </MockProvider>,
        );

        test('1 ', () => {
            expect(wrapper.baseElement).toMatchSnapshot();
            expect(wrapper.getByText('Apply').disabled).toBe(true);
        });
    });

    describe('Test 2', () => {
        test('1 ', () => {
            const wrapper = render(
                <MockProvider>
                    <MyComponent />
                </MockProvider>,
            );
            console.log(wrapper.getByText('Apply').disabled);
            expect(1).toBe(1);
        });
    });
});

但是,当我将第二个渲染功能移出测试时,它会出错:

describe('Parent', () => {
    afterEach(() => {
        cleanup();
        jest.resetModules();
    });

    describe('Test 1', () => {
        const wrapper = render(
            <MockProvider>
                <MyComponent />
            </MockProvider>,
        );

        test('1 ', () => {
            expect(wrapper.baseElement).toMatchSnapshot();
            expect(wrapper.getByText('Apply').disabled).toBe(true);
        });
    });

    describe('Test 2', () => {
        const wrapper = render(
            <MockProvider>
                <MyComponent />
            </MockProvider>,
        );
        test('1 ', () => {
            console.log(wrapper.getByText('Apply').disabled);
            expect(1).toBe(1);
        });
    });
});

我得到的错误是

  

找到带有文本的多个元素:应用

我可以在控制台中看到该组件被渲染了两次,因此我认为清除函数对于describe块一定不能正常工作。这很奇怪,因为我们已经进行了酶测试,并且设置和拆卸工作正常。

3 个答案:

答案 0 :(得分:4)

要了解这一点,我们需要对self.recRequest = FetchRequest(entity: Newdb.entity(), sortDescriptors: []) 如何运行测试以及Jest如何呈现我们的组件有一点了解。


开玩笑

考虑以下代码,然后尝试猜测输出结果

React Testing Library

输出(悬停查看)

首先描述
二描述
第一次测试
二次测试

请注意,所有describe('First describe', () => { console.log('First describe'); it('First test', () => { console.log('First test'); }); }); describe('Second describe', () => { console.log('Second describe'); it('Second test', () => { console.log('Second test'); }); }); 方法都是在测试开始运行之前初始化的。

这应该已经使您对问题有所了解,但是现在让我们看一下RTL。


反应测试库

考虑以下代码,并尝试猜测DOM在控制台中的外观:

describe

输出(悬停查看)

const Greeting = () => 'Hello world'; describe('First describe', () => { const wrapper = render(<Greeting />); it('First test', () => { console.log(wrapper.debug()); }); }); describe('Second describe', () => { render(<Greeting />); });

当我们没有为<body> <div>Hello world</div> <div>Hello world</div> </body>函数指定基本元素时,它总是使用相同的<body>

当我们不指定自定义容器时,RTL会添加包裹<div>Hello world</div>的{​​{1}}元素。

默认情况下,所有RTL查询都绑定到基本元素-在这种情况下为<div>Hello world</div>

因此

</body>


这是render函数的code in RTL外观。 (半伪代码)

document.body


要解决此问题

执行以下操作之一:

  1. <div>Hello world方法内调用document.body
  2. 在查询中指定getByText('Hello world'); // will find two elements and throw
  3. 为每个render指定不同的基本元素

答案 1 :(得分:2)

我遇到了一个单独的问题,但在其中发现了您的问题的可能答案。

Jest describe块按顺序运行,然后运行任何测试。 Source

因此,除了变量作用域外,您基本上不应该在describe块中执行代码。如果需要设置变量或呈现可在多个测试中使用的模拟,请将其放在生命周期方法中,例如beforeAllbeforeEach

答案 2 :(得分:0)

对此的另一种快速解决方案是在将组件传递给render()之前用“ React.Fragment”包装您的组件

test ('should find text in <Component />', () => {
   const {getByText} = render (<><Component /></>)
   const divElement = getByText (/Find Text/i)
   expect (divElement).toBeInTheDocument ()
})