【问题标题】:Mocking fetch with jest.fn() in React在 React 中使用 jest.fn() 模拟 fetch
【发布时间】:2021-01-29 09:11:39
【问题描述】:

我想知道为什么我需要将 fetch 模拟逻辑放入我的测试中以使其工作。

这是一个简单的例子:

在 useEffect 中使用 fetch 测试组件并在响应后更新状态:

// Test.jsx

import React, {useEffect, useState} from 'react'

export const Test = () => {

    const [description, setDescription] = useState<string | null>(null)

    const fetchData = async () => {
        const response = await fetch('https://dummyendpoint/');
        const parsed = await response.json();
        const description = parsed.value;
        setDescription(description);
    }

    useEffect(() => {
        fetchData();
    }, [])

    return (
        <div data-testid="description">
            {description}
        </div>
    )
};

export default Test;

测试逻辑:

// Test.test.js

import React from 'react';
import {render, screen} from '@testing-library/react';

import Test from "./Test";

global.fetch = jest.fn(() => Promise.resolve({
    json: () => Promise.resolve({
        value: "Testing something!"
    })
}));

describe("Test", () => {

    it('Should have proper description after data fetch', async () => {

        // need to put mock logic here to make it work

        render(<Test/>);
        const description = await screen.findByTestId('description');
        expect(description.textContent).toBe("Testing something!");
    });
})

如果我在测试文件的顶部保留 global.fetch 模拟,我会不断收到错误:

TypeError: Cannot read property 'json' of undefined
at const parsed = await response.json();

【问题讨论】:

    标签: javascript reactjs testing jestjs react-testing-library


    【解决方案1】:

    它不能按原样工作真的很奇怪。

    但我可以通过将设置移动到 beforeEach 块来修复它(我假设 beforeAll 也可以)。

    备份全局变量值,覆盖它以进行测试并恢复它是一种常见的模式。

    import React from 'react';
    import { render, screen } from '@testing-library/react';
    
    import Test from "./Test";
    
    
    
    describe("Test", () => {
        let originalFetch;
    
        beforeEach(() => {
            originalFetch = global.fetch;
            global.fetch = jest.fn(() => Promise.resolve({
                json: () => Promise.resolve({
                    value: "Testing something!"
                })
            }));
        });
    
        afterEach(() => {
            global.fetch = originalFetch;
        });
    
        it('Should have proper description after data fetch', async () => {
    
            // need to put mock logic here to make it work
    
            render(<Test />);
            const description = await screen.findByTestId('description');
            expect(description.textContent).toBe("Testing something!");
        });
    });
    

    【讨论】:

    • 谢谢你 - 非常有帮助:)
    猜你喜欢
    • 2017-12-19
    • 2020-03-03
    • 1970-01-01
    • 2019-08-11
    • 1970-01-01
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 2020-10-05
    相关资源
    最近更新 更多