繁体   English   中英

Jest 如何模拟 API 调用的实现

[英]Jest how to mock implementation of an API call

正如标题中所述,我试图模拟一个函数的实现。 我是测试 React 应用程序的新手。 我一直在互联网上寻找有关如何实现目标的数小时,所以让我解释一下。

我已经将 API 调用移动到另一个文件 (/utils/fetchGetCard.js):

export const fetchGetCard = (lang, word) => {
    return fetch("/getCard", {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({ lang: lang, word: word })
    }).then(response => response.text())
}

然后我在 SearchCard.jsx 中有一个功能组件:

    const searchCard = (event) => {

        event.preventDefault();
        event.stopPropagation();

        if (event.currentTarget.checkValidity() === true) {
            setValidated(false);
            fetchGetCard(selectInput.current.value, wordInput.current.value)
                .then(data => {
                    if (data === "ERR") {
                        console.log("Oops, something went wrong!");
                    } else if (data === "MISSING_WORD") {
                        console.log("Somehow your word wasn't passed to the backend");
                    } else {
                        if (data === '') {
                            showModal(wordInput.current.value);
                        } else {
                            setCardInfo(JSON.parse(data));
                            setCardLang(selectInput.current.value);
                            setFound(true);
                        }
                    }
                }).catch((error) => {
                    console.error('Error:', error);
                })
        } else {
            setValidated(true);
        }
    }

searchCard 函数绑定到 Form 组件的 onSubmit(来自 react-bootstrap)。 现在我想做一个测试,在其中渲染组件,然后输入一些信息并按下按钮。 在这部分中,我可能想模拟 API 调用以返回正确的硬编码数据。 最后,我想检查是否呈现了新组件(基于 API 数据)。 这是我到目前为止:

import SearchCard from './SearchCard.jsx';
import { render, waitFor } from '@testing-library/react';
import { fireEvent, screen } from "@testing-library/dom";
import { fetchGetCard } from "../utils/fetchGetCard.js";

jest.mock("../utils/fetchGetCard.js");

test("render SearchCard when card has been found", async () => {

    fetchGetCard.mockImplementation(() => {
        `{
            "word": "hund",
            "pronounciation": "ˈhʉn",
            "translation": [
                {
                    "type": "noun",
                    "meaning": "Its a dog mkay?",
                    "grammarNoun": {
                        "countable": "true",
                        "gender": "masculine",
                        "singularIndefinite": "en hund",
                        "singularDefinite": "hunden",
                        "pluralIndefinite": "hunder",
                        "pluralDefinite": "hundene"
                    }
                }
            ]
        }`
    });

    render(<SearchCard />);
    const testWordInput = screen.getByTestId("testWordInput");
    testWordInput.innerHTML = "hund";
    const testButtonSearch = screen.getByTestId("testButtonSearch");
    fireEvent.click(testButtonSearch);

    expect(fetchGetCard).toHaveBeenCalled();

    await waitFor(() => screen.findByTestId("testFoundCard"));

    expect(screen.getByText("hʉn")).toBeInTheDocument();
});

任何指导将不胜感激!

编辑 1:将 testWordInput.innerHTML 更改为 testWordInput.value 修复了它,似乎我已经成功地模拟了 fetchGetCard 函数。 不过,似乎 setCardInfo()、setCardLang() 和 setFound()(可能都是 setter)不起作用。 这些方法来自 useState 钩子。 他们应该工作得很好还是我可以做些什么来改变状态?

修复了问题:如编辑中所述,我设法从expect(fetchGetCard).toHaveBeenCalled()获得了正确的结果。 最后一件事是我的错,我实际上没有将“testFoundCard”ID 分配给 DOM 中的任何内容,结果是:

await waitFor(() => expect(screen.getByText("hundene")).toBeInTheDocument());

现在它起作用了!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM