我们在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上,当我们点击清除购物车按钮时,它会清除购物车并显示消息"您的购物车是空的".

我们正在try 在Jest/React Testing Library中编写一个单元测试.以下是我们的try :

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操作的控制台日志(log),这表明它没有被调用,因此断言 Your cart is empty !的测试失败.我们不确定为什么单击该按钮后操作不会被调度.有谁能帮帮我们吗?

PS:我们从失败的测试中得到的DOM struct 表明购物车还没有被清除.下面是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存储是常见的建议和实践.

示例:

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文档.

Reactjs相关问答推荐

Reaction Axios多部分/表单-数据数组不工作

如何通过回调函数获取多个值?

React Router:在没有手动页面刷新的情况下,路由不会更新内容

ReactJS:唯一项目的数量总和

如何使用react-router-dom保护嵌套在受保护路由中的嵌套路由?

React-chartjs-2:红色和绿色之间的差距

找不到名称setCometChat

ReactJS 共享上下文

React Wordpress Apache 在索引之外重新加载 -> 未找到页面

如何测试使用 React.createportal 呈现的组件?

使用登录保护 React 中的 SPA 应用程序 - 为什么这种方法不起作用?

NextJS htaccess 设置

使用 React Router v6 监听来自不同组件的组件状态变化

Select 建议后如何关闭 vscode 添加自动完成={}

如何使用react 路由将 url 参数限制为一组特定的值?

使用 useRef(uuid()) 的目的是什么?

如何用实际的br标签替换axios响应中的br标签?

单击三个按钮之一后如何显示特定按钮的内容?单击其中一个按钮后应隐藏所有按钮

ReactJS:按钮启用禁用更改 colored颜色

错误未捕获的错误:[App] 不是 组件. 的所有子组件必须是