首页 > 解决方案 > Jest 测试库 - 多次调用以在点击事件上加载数据

问题描述

我正在尝试在 onClick fireEvent 上测试加载更多按钮调用,但在模拟单击以触发加载数据时遇到问题。

零件:

class Items extends Component {

  // states
  
  componentDidMount() {
     this.getData()
  }

  getData() { ... 
     // get data from state - pagination # and data size
  }

  onLoadMore() {
      // increment pagination & offset on states
      this.getData()
  }

  render() {
      return (
        <div className='container'>
         {items.map((item, i) => {
              return (
                 <div className='item-box'>
                     // item info
                 </div>
              )
           }
         )}
         <button onClick={this.onLoadMore}>Load More</button>
        </div>
      )
  }
}

测试:

it('load more data on load more button click', () => {
    const Items = require('./default').default

    // set initial load values: initVals (2 items)
    // set second call values: secondVals (4 items)

    Items.prototype.getData = jest.fn()
    Items.prototype.getData.mockReturnValue(initVals)
    Items.prototype.getData.mockReturnValue(secondVals)

    const { container } = render(
      <Items
        fields={{ loadMore: true }}
      />
    )

    const button = screen.getByText('Load More')
    fireEvent.click(button)

    expect(container.querySelectorAll('.item-box').length).toBe(2)
    expect(container.querySelectorAll('.item-box').length).toBe(4)
  })

所以这只读取最后一次调用,找到 4 个项目。

.mockReturnValue()多次调用只会给我最后一次调用,而不是连续调用。我知道我用错了,但我不知道运行它的顺序。我的目标是使用第一个值(加载 2 个项目)初始化组件,然后在单击时加载更多(4 个项目)。

帮助?

标签: reactjstestingjestjsmockingreact-testing-library

解决方案


我认为您需要调用mockReturnValueOnce而不是mockReturnValue,并且您肯定需要在单击事件之前移动您的第一个断言。另外,我认为您的第二个断言应该期望6,而不是4.

您的测试的操作顺序应该是:

  • 设置模拟
  • 渲染组件
  • 在加载时断言初始值
  • 模拟点击事件
  • 单击后断言值。

这是一个演示此概念的简单示例:

// src/Demo.js
import React, { useState } from "react";

const Demo = ({ loadText }) => {
  const [text, setText] = useState("");

  return (
    <div>
      <button onClick={() => setText(loadText())}>Load</button>
      <p data-testid="data">{text}</p>
    </div>
  );
};

export default Demo;
// src/Demo.test.js
import { fireEvent, render, screen } from "@testing-library/react";
import '@testing-library/jest-dom'
import Demo from "./Demo";

test("callbacks", () => {
  const myMock = jest.fn();
  myMock.mockReturnValueOnce(2);
  myMock.mockReturnValueOnce(4);

  render(<Demo loadText={myMock} />);

  fireEvent.click(screen.getByRole("button"));
  expect(screen.getByTestId("data")).toHaveTextContent("2");

  fireEvent.click(screen.getByRole("button"));
  expect(screen.getByTestId("data")).toHaveTextContent("4");
});

此外,您嘲笑此函数 ( Items.prototype.getData = jest.fn()) 的方式对我来说似乎很奇怪。我建议您探索其他选项,例如(1)模拟 axios 或类似的库,(2)模拟一个 redux 存储,或(3)模拟你传递给这个组件的 props。


推荐阅读