清理方法在反应测试库中不起作用
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);
我正在测试我在 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);