我有这个 React 组件:
import React, { useState, useEffect } from "react";
import { BrowserRouter } from "react-router-dom";
import "./App.css";
import Home from "./Home";
import SnackOrBoozeApi from "./Api";
import NavBar from "./NavBar";
import { Route, Routes } from "react-router-dom";
import Menu from "./Menu";
import MenuItem from "./MenuItem";
import AddForm from './AddForm';
import NotFound from './NotFound';
import 'bootstrap/dist/css/bootstrap.min.css';
//renders loading screen if loading, else renders app.
function App() {
const [isLoading, setIsLoading] = useState(true);
const [snacks, setSnacks] = useState([]);
const [drinks, setDrinks] = useState([]);
useEffect(() => {
//get the list of snacks from the API and set state appropriately
async function getSnacks() {
setIsLoading(true);
let loadSnacks = await SnackOrBoozeApi.getGoodies('snacks');
setSnacks(loadSnacks);
setIsLoading(false);
}
//get the list of drinks from the API and set state appropriately
async function getDrinks() {
setIsLoading(true);
let loadDrinks = await SnackOrBoozeApi.getGoodies('drinks');
setDrinks(loadDrinks);
setIsLoading(false);
}
getSnacks();
getDrinks();
}, []);
if (isLoading) {
return <p>Loading …</p>;
}
return (
<div className="App">
<BrowserRouter>
<NavBar />
<main>
<Routes>
<Route path="/" element={<Home snacks={snacks} drinks={drinks}/>} />
<Route path="/snacks" element={<Menu items={snacks} type="snacks" />} />
<Route path="/snacks/:id" element={<MenuItem items={snacks} cantFind="/snacks" />}/>
<Route path="/drinks" element={<Menu items={drinks} type="drinks" />} />
<Route path='/drinks/:id' element={<MenuItem items={drinks} cantFind="/drinks" />}/>
<Route path='/add' element={<AddForm setSnacks={setSnacks} setDrinks={setDrinks}/>}/>
<Route path='*' element={<NotFound />}/>
</Routes>
</main>
</BrowserRouter>
</div>
);
}
export default App;
还有这个测试:
import {render, screen, waitFor, act} from '@testing-library/react';
import {test, expect, vi} from 'vitest';
import App from '../App';
import SnackOrBoozeApi from '../Api';
//mock the api call to gather appropriate data
vi.mock('SnackOrBoozeApi', () => ({
getGoodies: vi.fn((type) => {
if (type ==="snacks"){
return Promise.resolve([ {
"id": "nachos",
"name": "Nachos",
"description": "An American classic!",
"recipe": "Cover expensive, organic tortilla chips with Cheez Whiz.",
"serve": "Serve in a hand-thrown ceramic bowl, garnished with canned black olives"
},
{
"id": "hummus",
"name": "Hummus",
"description": "Sure to impress your vegan friends!",
"recipe": "Purchase one container of hummus.",
"serve": "Place unceremoniously on the table, along with pita bread."
}]);
}
if (type ==='drinks'){
return Promise.resolve([ {
"id": "martini",
"name": "Martini",
"description": "An ice-cold, refreshing classic.",
"recipe": "Mix 3 parts vodka & 1 part dry vermouth.",
"serve": "Serve very cold, straight up."
},
{
"id": "negroni",
"name": "Negroni",
"description": "A nice drink for a late night conversation.",
"recipe": "Mix equal parts of gin, Campari, and sweet vermouth.",
"serve": "Serve cold, either on the rocks or straight up."
}]);
}
})
}));
test('renders the App component', async () => {
await act (async () => {render(<App />)});
});
test('it matches snapshot', async () => {
let app;
await act(async () => {
app = render(<App />)
});
await waitFor(() => expect(app).toMatchSnapshot());
});
test('it displays loading message', async () => {
const {getByText} = render(<App/>);
expect(getByText('Loading', {exact: false})).toBeInTheDocument();
});
test('fetches and displays api data', async () => {
await act(async () => {
render(<App />);
});
await waitFor(() => expect(screen.getByText('Snacks: 2')).toBeInTheDocument());
await waitFor(() => expect(screen.getByText('Drinks: 2')).toBeInTheDocument());
});
但是最终测试没有通过,因为它似乎实际上是在调用 API,而不是模拟它。它返回 Snacks: 5 和 Drinks: 7,这是数据库中的数字。快照测试也没有通过,因为它返回的是加载状态,但我更关心为什么我的模拟不起作用。
我尝试了不同的编写模拟的方法(doMock、returnResolvedValueOnce 等)以及 act 和 wait 的各种组合,但我没有运气。烟雾测试和加载状态测试确实通过了。
在模拟服务器请求时,建议使用
msw
并使用 server.use()
模拟响应。
如果你仍然想用这种方法工作,我认为导入路径不正确
vi.mock('SnackOrBoozeApi', () => ({
这里应该是相对路径,我不知道确切的环境,但是从你的代码来看,它看起来应该是
vi.mock('/Api/SnackOrBoozeApi', () => ({
或者实际的相对路径是什么。 (p.s如果您使用的是VSCode,您可以轻松单击文件本身的相对路径)