如何在Jest与React Testing Library中测试Fetch请求URL的exact参数
解决方案
一、修正前端代码
原代码核心问题是请求URL在页面加载时就固定,不会随单选框实时状态更新,需将获取单选框状态、构建请求URL的逻辑移到getData函数内部:
修正后的完整代码
<!DOCTYPE html> <html> <body> <h2>HTML Forms</h2> <form> <label for="fname">Search:</label><br> <input type="text" id="fname" name="fname" value="John"> <input type="radio" id="myCheck" name="fav_language" value="HTML"> <label for="myCheck">Exact</label><br><br> <input type="submit" id="getData" value="Submit"> </form> <script> const initDetails = { method: 'get', headers: { "Content-Type": "application/json; charset=utf-8" }, mode: "cors" } function getData(e) { e.preventDefault(); // 阻止表单默认跳转行为 const checkBox = document.getElementById("myCheck"); const checkBoxChecked = checkBox.checked ? "true" : "false"; const uri = `https://jsonplaceholder.typicode.com/posts?exact=${checkBoxChecked}`; fetch(uri, initDetails) .then(response => { if (response.status !== 200) { console.log('Looks like there was a problem. Status Code: ' + response.status); return; } console.log(response.headers.get("Content-Type")); return response.json(); }) .then(myJson => { console.log(JSON.stringify(myJson)); }) .catch(err => { console.log('Fetch Error :-S', err); }); } window.onload=function() { const myButton = document.getElementById("getData"); myButton.addEventListener('click', getData); } </script> </body> </html>
二、React Testing Library测试用例
通过RTL模拟用户交互,拦截fetch请求,验证URL是否包含正确的exact参数:
测试代码
import { render, screen, fireEvent } from '@testing-library/react'; // 若测试原生HTML页面,可替换为@testing-library/dom // 全局拦截fetch请求 beforeEach(() => { global.fetch = jest.fn(() => Promise.resolve({ status: 200, json: () => Promise.resolve([]), headers: { get: () => 'application/json' } }) ); }); afterEach(() => { jest.clearAllMocks(); }); test('单选框勾选时,请求URL包含?exact=true', () => { // 加载页面结构 document.body.innerHTML = ` <h2>HTML Forms</h2> <form> <label for="fname">Search:</label><br> <input type="text" id="fname" name="fname" value="John"> <input type="radio" id="myCheck" name="fav_language" value="HTML"> <label for="myCheck">Exact</label><br><br> <input type="submit" id="getData" value="Submit"> </form> `; // 引入页面业务逻辑 const initDetails = { method: 'get', headers: { "Content-Type": "application/json; charset=utf-8" }, mode: "cors" }; function getData(e) { e.preventDefault(); const checkBox = document.getElementById("myCheck"); const checkBoxChecked = checkBox.checked ? "true" : "false"; const uri = `https://jsonplaceholder.typicode.com/posts?exact=${checkBoxChecked}`; fetch(uri, initDetails); } document.getElementById("getData").addEventListener('click', getData); // 模拟用户操作 fireEvent.click(screen.getByLabelText('Exact')); fireEvent.click(screen.getByRole('button', { name: 'Submit' })); // 断言验证 expect(fetch).toHaveBeenCalledTimes(1); const requestUrl = fetch.mock.calls[0][0]; expect(requestUrl).toContain('?exact=true'); }); test('单选框未勾选时,请求URL包含?exact=false', () => { document.body.innerHTML = ` <h2>HTML Forms</h2> <form> <label for="fname">Search:</label><br> <input type="text" id="fname" name="fname" value="John"> <input type="radio" id="myCheck" name="fav_language" value="HTML"> <label for="myCheck">Exact</label><br><br> <input type="submit" id="getData" value="Submit"> </form> `; const initDetails = { method: 'get', headers: { "Content-Type": "application/json; charset=utf-8" }, mode: "cors" }; function getData(e) { e.preventDefault(); const checkBox = document.getElementById("myCheck"); const checkBoxChecked = checkBox.checked ? "true" : "false"; const uri = `https://jsonplaceholder.typicode.com/posts?exact=${checkBoxChecked}`; fetch(uri, initDetails); } document.getElementById("getData").addEventListener('click', getData); fireEvent.click(screen.getByRole('button', { name: 'Submit' })); expect(fetch).toHaveBeenCalledTimes(1); const requestUrl = fetch.mock.calls[0][0]; expect(requestUrl).toContain('?exact=false'); }); test('请求URL未包含exact参数时抛出错误', () => { document.body.innerHTML = ` <h2>HTML Forms</h2> <form> <label for="fname">Search:</label><br> <input type="text" id="fname" name="fname" value="John"> <input type="radio" id="myCheck" name="fav_language" value="HTML"> <label for="myCheck">Exact</label><br><br> <input type="submit" id="getData" value="Submit"> </form> `; // 模拟错误的业务逻辑(未添加exact参数) function badGetData(e) { e.preventDefault(); const uri = 'https://jsonplaceholder.typicode.com/posts'; fetch(uri); } document.getElementById("getData").addEventListener('click', badGetData); fireEvent.click(screen.getByRole('button', { name: 'Submit' })); const requestUrl = fetch.mock.calls[0][0]; if (!requestUrl.includes('exact')) { throw new Error('请求URL未包含exact查询参数'); } });
关键说明
- 必须将URL构建逻辑放在
getData内部,才能获取单选框的实时状态 - 测试时通过
jest拦截全局fetch,借助mock.calls获取请求URL进行断言 - 最后一个测试用例会主动校验URL,不满足条件则抛出错误
内容的提问来源于stack exchange,提问作者Manikandan Selva Cse
相关产品推荐
相关产品推荐

