【问题标题】:Testing components that depend on Context using React Testing Library or Jest使用 React 测试库或 Jest 测试依赖于 Context 的组件
【发布时间】:2021-08-08 00:15:51
【问题描述】:

我所有的组件都从上下文中获取数据和方法。我想测试-至少-“组件渲染”案例,但是当然,当我尝试在测试案例中渲染组件时,它找不到来自上下文的方法/函数和数据。我找不到使用 React 测试库或 Jest 将 Context 值传递给测试用例的方法(我需要使用这些库,没有酶)

假设我想测试一个简单的过滤器组件。

上下文(我猜是原始用法)

import { useState, useEffect, createContext } from "react";

const Context = createContext();

const ContextProvider = ({ children }) => {
  const [books, setBooks] = useState([]);
  // other data and method code..

  const handleFilter = (value) => {
    const filteredBooks = [...books];
    if (books.length > 0) {
      switch (value) {
        case "alphabetical":
          filteredBooks.sort((a, b) => a.title - b.title);
          setBooks(filteredBooks);
          break;
        case "publishdate":
          filteredBooks.sort(
            (a, b) => b.first_publish_year - a.first_publish_year
          );
          setBooks(filteredBooks);
          break;
        default:
          setBooks(filteredBooks);
      }
    }
  };

  return (
    <Context.Provider value={{ handleFilter }}>
      {children}
    </Context.Provider>
  );
};

export { ContextProvider, Context };

过滤器

import { useContext } from "react";
import { Context } from "../context/Context";

function Filter() {
  const { handleFilter } = useContext(Context);

  return (
    <div className="filter" data-testid="filter-test">
      <div className="filter-content">
        <select
          defaultValue="none"
          className="filter-btn"
          onChange={(e) => handleFilter(e.target.value)}
        >
          <option value="none" defaultValue disabled>
            Filter Results
          </option>
          <option value="alphabetical">Alphabetically</option>
          <option value="publishdate">Publish Date (newest)</option>
        </select>
      </div>
    </div>
  );
}

export default Filter;

Filter.test.js

import { render, screen, cleanup } from '@testing-library/react';
import Filter from './Filter';

test('renders Filter component without crashing', () => {
  // I need to pass handleFilter function using Context somehow
  render(<Filter />);
  const filterComponent = screen.getByTestId('filter-test');
  expect(filterComponent).toBeInTheDocument();
});

如果你想查看所有代码:https://codesandbox.io/s/inspiring-bhaskara-0s98g

【问题讨论】:

标签: reactjs react-testing-library


【解决方案1】:

执行此操作的简单方法是将上下文提供程序作为render() 的第一个参数的包装器传递:

import { render, screen, cleanup } from '@testing-library/react';
import Filter from './Filter';

// import your context; it will include the provider
import { Context } from "../context/Context";

test('renders Filter component without crashing', () => {
  const contextValue = { handleFilter: () => {} };
  render(
    <Context.Provider value={contextValue}>
      <Filter />
    </Context.Provider>
  );

  const filterComponent = screen.getByTestId('filter-test');
  expect(filterComponent).toBeInTheDocument();
});

另一种方法是提供你的上下文作为渲染的包装器:

import { render, screen, cleanup } from '@testing-library/react';
import Filter from './Filter';

// import your context; it will include the provider
import { Context } from "../context/Context";

test('renders Filter component without crashing', () => {
  const contextValue = { handleFilter: () => {} };
  const wrapper = ({ children }) => (
    <Context.Provider value={contextValue}>
      {children}
    </Context.Provider>
  );

  render(<Filter />, { wrapper });

  const filterComponent = screen.getByTestId('filter-test');
  expect(filterComponent).toBeInTheDocument();
});

以上两种方法中的任何一种都应该有效

【讨论】:

  • 你觉得哪个更好?
  • 我更喜欢第一个,它更直接一些
猜你喜欢
  • 2020-10-18
  • 2020-01-11
  • 1970-01-01
  • 2022-08-10
  • 2021-04-20
  • 1970-01-01
  • 2021-12-06
  • 2020-03-24
  • 2020-06-14
相关资源
最近更新 更多