You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 22:21:00