您好,我是单元测试的新手,我有一个组件可以渲染产品列表并显示这些列表。我在该组件中还有一个功能,可以按价格范围过滤这些产品。我使用了 ReactSlider,它基本上更新了两个状态变量“priceFrom”和“priceTo”,当这些状态变量发生变化时,我触发了一个根据这些价格过滤产品的函数。所以我想在玩笑中测试类似的功能。开玩笑有可能吗?如果是这样,我怎样才能实现这一点,如果不是,我可以采取哪种替代方法来完成该组件的单元测试。谢谢。该组件的代码如下。请注意,在下面的代码中,当 ReactSlider 更新任何值时,filterItem 函数会过滤产品并更新 ui。
import React, { useEffect, useState, useContext } from "react";
import { useParams } from "react-router-dom";
import styles from './productsList.module.css';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faSpinner } from '@fortawesome/free-solid-svg-icons';
import Backdrop from "../../Others/Backdrop/backdrop";
import Modal from '../../Others/Modal/modal';
import ReactPaginate from 'react-paginate';
import ReactSlider from 'react-slider';
import { disableScroll } from "../../Others/HelperFunction/helperFunction";
import { ContextProvider } from "../../Others/AuthContext/authContext";
import './slider.css';
const ProductsList = () => {
const context = useContext(ContextProvider);
const productId = useParams().productId;
const [sidebar, setSidebar] = useState(false);
const [backdrop, setBackdrop] = useState(false);
const [products, setProducts] = useState([]);
const [filteredProducts, setFilteredProducts] = useState([]);
const [error, setError] = useState(false);
const [status, setStatus] = useState('');
const [modal, setModal] = useState(false);
const [priceFrom, setPriceFrom] = useState(0);
const [priceTo, setPriceTo] = useState(10000);
const [itemOffset, setItemOffset] = useState(0);
const [itemNotFound, setItemNotFound] = useState(false);
const itemPerPage = 9;
const endOffset = itemOffset + itemPerPage;
let pageCount = 0;
if (filteredProducts.length){
pageCount = Math.ceil(filteredProducts.length / itemPerPage);
}
else {
pageCount = Math.ceil(products.length / itemPerPage);
}
const handlePageClick = (event) => {
if (filteredProducts.length){
const newOffset = (event.selected * itemPerPage) % filteredProducts.length;
setItemOffset(newOffset);
}
else {
const newOffset = (event.selected * itemPerPage) % products.length;
setItemOffset(newOffset);
}
}
useEffect(() => {
window.scrollTo(0, 0);
if (context.data !== undefined){
const product = context.data[productId] !== undefined ? context.data[productId] : [];
if (product.length){
setProducts(product);
setStatus('success');
}
else {
setStatus('not found');
}
}
}, [context.data] );
useEffect(() => {
window.scrollTo(0, 0);
}, [itemOffset, filteredProducts.length]);
useEffect(() => {
if (backdrop){
disableScroll();
}
else {
window.onscroll = () => {
}
}
}, [backdrop])
let defaultView = Array.from(Array(12).keys()).map(item => {
return
});
if (products.length){
if (!itemNotFound && filteredProducts.length){
defaultView = filteredProducts.slice(itemOffset, endOffset).map(item => {
return
});
}
else if (itemNotFound) {
defaultView =
Nothing found based on your range
}
else {
defaultView = products.slice(itemOffset, endOffset).map(item => {
return
});
}
}
else if(status === 'not found') {
defaultView =
Nothing found
}
const filterItem = () => {
if (priceFrom && priceTo) {
const filteredData = products.filter(item => Number(item.price) >= priceFrom && Number(item.price) <= priceTo);
if (filteredData.length){
setItemNotFound(false)
setFilteredProducts(filteredData);
setSidebar(false);
setBackdrop(false);
}
else {
setItemNotFound(true);
setItemOffset(0);
setSidebar(false);
setBackdrop(false);
}
}
}
const resetFilter = () => {
setPriceFrom(0);
setPriceTo(1000);
setFilteredProducts([]);
}
const openSidebar = () => {
if (!sidebar){
setSidebar(true);
setBackdrop(true);
}
}
const closeSidebar = () => {
if (sidebar){
setSidebar(false);
setBackdrop(false);
}
else {
setBackdrop(false);
}
}
let displayStatus =
Something went wrong
Please try again
if (status === 'database error'){
displayStatus =
Database error
Please try again or contact the admin
}
return (
<>
{displayStatus}
Show Sidebar
Price Range
`Thumb value ${state.valueNow}`}
renderThumb={(props, state) => {state.valueNow}}
minDistance={1}
onChange={([v1, v2]) => {
setPriceFrom(v1);
setPriceTo(v2);
}}
pearling
/>
{products.length ? products[0].category : null}
{defaultView}
>
)
}
export default ProductsList; Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
我可以为您提供一些与您的问题相关的建议
检查一个可以帮助您测试 React 元素的库(例如react-testing-library https://testing-library.com/docs/react-testing-library/intro/)
通常来自另一个库的东西不会被测试,因为我们假设库本身已经测试过它(在这种情况下是 ReactSlider 库
尝试将组件拆分为更小的组件,这样更容易测试(您可以使用 props),并且每个组件内部的依赖关系会更少
我们可以将这里的测试分为两种不同的测试E2E和单元测试,E2E是当您使用模拟用户交互的工具时,在这种情况下您可以模拟用户移动范围滑块,看看之后会发生什么(为此,您可以使用 cypress 或 selenium)这些工具像人类一样在浏览器中运行,单元测试允许您测试功能、组件输入和输出,在这里您可以也模拟点击和交互,但对于用户交互来说,它们不如 E2E 强大,因为单元测试(在本例中是开玩笑的工具)在 JSDOM 中运行测试,JSDOM 是真实浏览器的模拟(简单来说)
为了解决这个问题,我将执行以下操作
赛普拉斯:https://www.cypress.io/
硒: https://www.selenium.dev/
请记住,E2E 和单元测试是两种为您提供最佳服务的方法,具体取决于您要寻找的内容,每种方法都可以模拟用户交互,但其背后的引擎不同
希望对你有帮助