我们在 React 应用程序中有一个购物车组件:
import { useDispatch, useSelector } from "react-redux";
import ItemList from "./ItemList";
import { clearCart } from "../slice/cartSlice";
const Cart = () => {
const dispatch = useDispatch();
const cartItems = useSelector((store) => store.cart.items);
const handleClearCart = () => {
console.log("Here in the handle clear cart onClick event handler");
console.log("clearCart function is ", clearCart);
dispatch(clearCart());
};
return (
<div>
<h1> Cart </h1>
{cartItems.length != 0 && (
<button
onClick={handleClearCart}
>
Clear Cart
</button>
)}
{cartItems.length ? (
<div>
<ItemList items={cartItems} />
</div>
) : (
<h3> Your cart is empty !</h3>
)}
</div>
);
};
export default Cart;
这是我们正在使用的 cartSlice :
import { createSlice, current } from "@reduxjs/toolkit";
const cartSlice = createSlice({
name: "cart",
initialState: { items: [] },
reducers: {
addItem: (state, action) => {
state.items.push(action.payload);
},
removeItem: (state, action) => {
const filteredList = state.items.filter(
(item, index) => index != action.payload
);
return {
...state,
items: filteredList,
};
},
clearCart: (state) => {
console.log("Here in the clear cart reducer");
state.items.length = 0;
},
},
});
export const { addItem, removeItem, clearCart } = cartSlice.actions;
export default cartSlice.reducer;
在 UI 上,当我们单击清除购物车按钮时,它会清除购物车并显示消息“您的购物车为空”。
我们正在尝试在 Jest/React 测试库中编写相同的单元测试。这是我们的尝试:
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import "@testing-library/jest-dom";
import { Provider } from "react-redux";
import configureMockStore from "redux-mock-store";
import mockStoreInfo from "../__mocks__/storeMock";
import Cart from "../src/components/Cart";
test("should clear cart when click on clear cart in cart component", async () => {
render(
<Provider store={storeMock}>
<Cart />
</Provider>
);
const clearCartButton = screen.getByRole("button", { name: "Clear Cart" });
expect(clearCartButton).toBeInTheDocument();
console.log("clearCart button is", clearCartButton);
fireEvent.click(clearCartButton);
expect(await (screen.getByText(" Your cart is empty !"))).toBeInTheDocument();
});
从我们可以看到,
clear Cart
按钮已被记录并且是一个有效的按钮。 handleClearCart
函数也被调用,我们也可以打印 clearCart
函数体。但是,我们无法从 CartSlice 中的 clearCart
操作中看到控制台日志,这表明它没有被调用,因此断言 Your cart is empty !
的测试失败。我们不确定为什么单击该按钮时没有调度该操作。有人可以帮助我们吗?
PS:我们从失败的测试中得到的 DOM 结构表明购物车尚未被清除。这是 DOM:
<body>
<div>
<div class="cart-container" data-testid="cart">
<h1 class="cart-heading">Cart</h1>
<button class="clear-cart" data-testid="clear-cart">Clear Cart</button>
<div class="cart-items" data-testid="cart-items-list">
<div>
<div class="menu-item">
<div class="sc-guDLey byrpfT">
<div class="menu-header">
<span> Al Fungi Gourmet-Pizza </span>
<span> - ₹ 549 </span>
</div>
<p class="accordion-body-description">
Gourmet mushroom pizza on a cheesy Mozzarella base with
jalapenos & cherry tomatoes.
</p>
</div>
<div class="sc-beySPh fSyZNZ">
<img
class="accordion-image"
src="https://res.cloudinary.com/swiggy/image/upload/fl_lossy,f_auto,q_auto,w_508,h_320,c_fill/4ffebb537f043e94e09e928f48e640e9"
/>
<button class="accordion-button-delete">Remove -</button>
</div>
</div>
<div class="menu-item">
<div class="sc-guDLey byrpfT">
<div class="menu-header">
<span> Butterscotch Mousse Cake </span>
<span> - ₹ 103.81 </span>
</div>
<p class="accordion-body-description">
Sweet temptation! Butterscotch flavored mousse
</p>
</div>
<div class="sc-beySPh fSyZNZ">
<img
class="accordion-image"
src="https://res.cloudinary.com/swiggy/image/upload/fl_lossy,f_auto,q_auto,w_508,h_320,c_fill/e91002ccf7239fffeceaab4956a15a3a"
/>
<button class="accordion-button-delete">Remove -</button>
</div>
</div>
<div class="menu-item">
<div class="sc-guDLey byrpfT">
<div class="menu-header">
<span> Choco Lava Cake </span>
<span> - ₹ 109 </span>
</div>
<p class="accordion-body-description">
Chocolate lovers delight! Indulgent, gooey molten lava inside
chocolate cake
</p>
</div>
<div class="sc-beySPh fSyZNZ">
<img
class="accordion-image"
src="https://res.cloudinary.com/swiggy/image/upload/fl_lossy,f_auto,q_auto,w_508,h_320,c_fill/517791a68253a9a5084664b470f6e115"
/>
<button class="accordion-button-delete">Remove -</button>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
redux-mock-store
已经过时了。在单元测试中创建真正的 Redux 存储是常见的建议和实践。 Redux-Toolkit 创建的商店已集成并默认启用 Thunk 中间件。
示例:
import React from 'react';
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import "@testing-library/jest-dom";
import { configureStore } from "@reduxjs/toolkit"; // <-- create real store
import { Provider } from 'react-redux';
import reducer from '../path/to/rootReducer'; // <-- import reducer
import Cart from "../src/components/Cart";
const preloadedState = {
// any initial state necessary for the unit tests
};
const store = configureStore({
preloadedState,
reducer,
});
const Providers = ({ children }) => (
<Provider store={store}>
{children}
</Provider>
);
test("should clear cart when click on clear cart in cart component", async () => {
render(<Cart />, { wrapper: Providers });
const clearCartButton = screen.getByRole("button", { name: "Clear Cart" });
expect(clearCartButton).toBeInTheDocument();
console.log("clearCart button is", clearCartButton);
fireEvent.click(clearCartButton);
expect(await (screen.getByText(" Your cart is empty !"))).toBeInTheDocument();
});
请参阅 Redux Writing Tests 文档,了解更多一般测试信息和策略。