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

React测试报错:无法找到元素文本,第二个测试用例未通过

React测试用例失败问题排查与解决

问题描述

第二个React测试用例报错unable to find element with the text,第一个测试可正常找到导航栏的'Products'文本,但查找'£499,99'时失败;通过screen.debug()发现<Products />组件未在测试中渲染(页面实际能正常加载该组件),尝试过async/await仍未解决,怀疑与路由配置相关。

相关代码

App.js

import logo from './logo.svg';
import './App.css';
import { useState } from 'react';
import { Link, Route, Routes } from "react-router-dom";
import Home from "./pages/home.js";
import Products from './pages/products.js';
import { HashRouter } from 'react-router-dom';
import Nav from './nav.js'
import './MaterialDesign-Webfont-master/css/materialdesignicons.css';

function App() {
  const productArray = [];

  productArray[0] = new Image();
  productArray[0].src = 'imgs/smartphone-one.jpg';
  productArray[0].dataset.key = '0';
  productArray[0].alt = 'Blueberry 5000 S';
  productArray[0].dataset.price = '£499.99';

  productArray[1] = new Image();
  productArray[1].src = 'imgs/smartphone-two.jpg';
  productArray[1].dataset.key = '1';
  productArray[1].alt = 'Banana 12';
  productArray[1].dataset.price = '£999.99';

  productArray[2] = new Image();
  productArray[2].src = 'imgs/smartphone-three.jpg';
  productArray[2].dataset.key = '2';
  productArray[2].alt = 'Meg 3';
  productArray[2].dataset.price = '£799.99';

  productArray[3] = new Image();
  productArray[3].src = 'imgs/smartphone-four.jpg';
  productArray[3].dataset.key = '3';
  productArray[3].alt = 'Communicator 5000';
  productArray[3].dataset.price = '£399.99';

  productArray[4] = new Image();
  productArray[4].src = 'imgs/smartphone-five.jpg';
  productArray[4].dataset.key = '4';
  productArray[4].alt = 'Simplex 2';
  productArray[4].dataset.price = '£99.99';

  return ( 
    <HashRouter>
      <Nav/> 
      <div>
        <Routes>
          <Route path="/" element={<Home/>} />
          <Route path="/products" element={<Products prods={productArray}/>} />
        </Routes>
      </div>
    </HashRouter>
  );
}

export default App;

Products组件

import React from 'react';

function Products({ prods }) {
  return (
    <>
      <h2 className="products-title">Products</h2>
      <div className="products" data-testid="products-div">
        {prods.map(prod => {
          return (
            <div 
              className="product" 
              style={{
                backgroundImage: `url("${prod.src}")`,
                width: 400,
                height: 400,
                display: 'flex',
                flexFlow: 'column nowrap',
                alignItems: 'center',
                backgroundRepeat: 'no-repeat',
                backgroundPosition: 'top',
                backgroundSize: 'contain',
              }} 
              id={prod.dataset.key}
            >  
              <p className="prod-copy">{prod.alt}</p>
              <p className="prod-price">{prod.dataset.price}</p>
              <button className="add">Add to cart</button>
            </div>
          );
        })}
      </div>
    </>
  );
}

export default Products;

App.test.js

import { render, screen } from '@testing-library/react';
import App from './App';
import React from "react";
import Products from './pages/products';

test('Product in nav', () => {
  render(<App />);
  expect(screen.getByText('Products')).toBeInTheDocument();
});

test('phones', () => {
  render(<App />);
  expect(screen.getByText('£499,99')).toBeInTheDocument();
});

问题原因与解决方案

1. 路由未切换至Products页面

测试默认渲染App时,路由处于根路径/,对应渲染Home组件,而非Products组件。需在测试中指定路由路径或直接渲染Products组件:

方案一:直接渲染Products组件

跳过路由,直接传入测试所需数据渲染组件,适合单元测试:

test('phones - 直接渲染组件', () => {
  // 构造测试用产品数据
  const testProducts = [
    {
      alt: 'Blueberry 5000 S',
      dataset: { price: '£499.99' },
      src: 'imgs/smartphone-one.jpg'
    }
  ];
  render(<Products prods={testProducts} />);
  expect(screen.getByText('£499.99')).toBeInTheDocument();
});

方案二:通过路由切换至/products路径

使用MemoryRouter指定初始路由,模拟真实路由场景:

import { MemoryRouter } from 'react-router-dom';

test('phones - 通过路由跳转', async () => {
  render(
    <MemoryRouter initialEntries={['/products']}>
      <App />
    </MemoryRouter>
  );
  // 路由切换为异步操作,使用findByText等待元素出现
  const priceElement = await screen.findByText('£499.99');
  expect(priceElement).toBeInTheDocument();
});

2. 文本匹配错误

代码中产品价格为£499.99(小数点),但测试用例中写的是£499,99(逗号),需修正测试中的文本内容。

3. 其他潜在问题

  • Products组件中import React from 'react-dom'错误,应改为import React from 'react';
  • App中使用new Image()创建产品数据不合理,Image是DOM元素,建议改用普通对象存储数据,避免潜在问题:
    const productArray = [
      {
        src: 'imgs/smartphone-one.jpg',
        key: '0',
        alt: 'Blueberry 5000 S',
        price: '£499.99'
      },
      // 其他产品...
    ];
    
    同时修改Products组件中数据的读取方式,比如{prod.price}替代{prod.dataset.price}。

内容的提问来源于stack exchange,提问作者Roblou

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 08:39:56