清理方法在反应测试库中不起作用

Cleanup method is not working in react testing library

我正在测试我在 React js 中构建的待办事项应用程序,为了测试,我正在使用 React 测试库问题是当我 运行 我的第一个测试影响了他下面写的其他测试,我尝试了很多可能的解决方案,但找不到这个的解决方案

这是我的 AddTodo 组件

const AddTodo = () => {
  //get store todo list from local storage
  const getTodoList = () => {
    let result = JSON.parse(localStorage.getItem("list"));
    if (result) return result;
    else return [];
  };

  //define states
  const [todo, setTodo] = useState("");
  const [todoList, setTodoList] = useState(getTodoList());
  const [counter, setCounter] = useState(todoList.length);

  //Click Handler
  const handleClick = () => {
    setCounter(counter + 1);
    let obj = { id: counter, todo: todo };
    setTodoList([...todoList, obj]);
    setTodo("");
  };

  //Adding Todo Items in Local Storage
  useEffect(() => {
    localStorage.setItem("list", JSON.stringify(todoList));
  }, [todoList]);

  //Input Form Change Handler
  const handleChange = (e) => {
    setTodo(e.target.value);
  };

  //remove completed todos
  const removeTodo = (todoId) => {
    let list = getTodoList();
    let result = list.filter((l) => {
      return l.id !== todoId;
    });
    setTodoList(result);
  };

  return (
    <>
      <header>Todo App</header>
      <div className={style.inputField}>
        <input
          type="text"
          placeholder="Add your new todo"
          onChange={handleChange}
          value={todo}
          data-testid="input"
        />
        <button onClick={handleClick} data-testid="btn">
          <i className="fas fa-plus"></i>
        </button>
      </div>
      <ul className={style.todoList}>
        {todoList.map((l, index) => (
          <Todo todo={l.todo} key={index} onClick={removeTodo} id={l.id} />
        ))}
      </ul>
    </>
  );
};

添加 Todo 组件测试

import { render, screen, fireEvent, cleanup } from "@testing-library/react";
import AddTodo from "../AddTodo";

beforeEach(() => {
  render(<AddTodo />);
});

/**
 * Helper Methods
 * These methods get the most frequntly used elements for testing
 * */

const addTask = (task) => {
  const inputEl = screen.getByPlaceholderText("Add your new todo");
  const btnEl = screen.getByTestId("btn");

  task.forEach((el) => {
    fireEvent.change(inputEl, { target: { value: el } });
    fireEvent.click(btnEl);
  });
};

const removeTask = (task) => {
  task.forEach((tsk) => {
    fireEvent.click(tsk);
  });
};

/**
 * Unit Testing
 * Test the each part of component
 **/

describe("Unit Testing of Component", () => {
  it("should be empty by deafult", () => {
    const inputEl = screen.getByTestId("input");
    expect(inputEl.value).toBe("");
  });

  it("should change input value", () => {
    const inputEl = screen.getByTestId("input");
    fireEvent.change(inputEl, {
      target: {
        value: "hello i am test",
      },
    });
    expect(inputEl.value).toBe("hello i am test");
  });

  it("should empty input field after each click", () => {
    const inputEl = screen.getByTestId("input");
    const btnEl = screen.getByTestId("btn");
    fireEvent.change(inputEl, {
      target: {
        value: "hello test1 ",
      },
    });

    fireEvent.click(btnEl);
    expect(inputEl.value).toBe("");
  });
});

/**
 * Integration Testing
 * Test 2 components 'Todo' and 'AddTodo'
 **/

describe("Integration Testing of Component", () => {
  afterEach(() => {
    cleanup();
  });

  it("should add value to todo List", () => {
    const inputEl = screen.getByPlaceholderText("Add your new todo");
    const btnEl = screen.getByTestId("btn");
    fireEvent.change(inputEl, {
      target: {
        value: "hello test1",
      },
    });

    fireEvent.click(btnEl);
    const listEl = screen.getByText(/hello test1/i);
    expect(listEl).toBeInTheDocument;
  });

  it("should add multiple value to todo List", () => {
    addTask(["test 1", "test 2", "test 3", "test 4", "test 5"]);
    const listEl = screen.getAllByTestId("btn2");
    expect(listEl.length).toBe(5);
  });

  it("should remove when click on check button", () => {
    const listEl = screen.getAllByTestId("btn2");

    removeTask(listEl);

    expect(listEl.length).toBe(0);
  });
});

Todo 组件

  return (
    <>
      <li data-testid="title">
        {props.todo}
        <span className={style.icon} data-testid="icon">
          <i
            className="fas fa-check"
            data-testid="btn2"
            onClick={() => {
              props.onClick(props.id);
            }}
          ></i>
        </span>
      </li>
    </>
  );
};

尝试从 AddTodo 组件中删除 localstorage 方法。我认为这是导致意外行为的原因。 (组件已正确重置,但重新渲染时,它会从本地存储中读取)

如果可行,您可以读取 localstorage 用法并在测试中模拟它:

describe("Todo tests", ()=>{
  const setItemMock = jest.fn();
  const getItemMock = jest.fn();
  beforeEach(() => {
    Storage.prototype.setItem = setItemMock;
    Storage.prototype.getItem = getItemMock;
  });

  afterEach(() => {
    setItemMock.mockRestore();
    getItemMock.mockRestore();
  });
  // your tests
});

有了这个,您还可以检查是否调用了本地存储函数:expect(getItemMock).toHaveBeenCalledTimes(1);