【问题标题】:React state not being updated in Jest while working in the application在应用程序中工作时,Jest 中未更新 React 状态
【发布时间】:2021-04-22 10:25:32
【问题描述】:

当我单击按钮时,它会将值增加输入中写入的数量,当我在应用程序中执行此操作时它会起作用,但是当我尝试使用 Jest 并且首先 fireEvent.change() 将输入的值设置为 10 然后fireEvent.click() 在按钮上它不会增加它并且值保持在0

这是我得到的错误:

expect(received).toBe(expected) // Object.is equality

   Expected: 10
   Received: 0

     33 |     fireEvent.click(btnPlus);
     34 |
   > 35 |     expect(parseInt(val.textContent)).toBe(10);
        |                                       ^
     36 |   });
     37 | });
     38 |

这里是测试文件:

import React from 'react';
import Counter from './Counter';
import { render, fireEvent } from '@testing-library/react';
describe('Counter works', () => {
  let comp;
  let inp;
  let btnPlus;
  let val;
  beforeAll(() => {
    comp = render(<Counter />);
    inp = comp.getByTestId('inp');
    btnPlus = comp.getByTestId('btn-+');
    val = comp.getByTestId('counter-value');
  });

  it('Counter exists', () => {
    expect(comp).toBeTruthy();
  });
  it('Input works', () => {
    expect(inp.value).toBe('');

    fireEvent.change(inp, {
      target: {
        value: 10,
      },
    });

    expect(parseInt(inp.value)).toBe(10);

    fireEvent.click(btnPlus);

    expect(parseInt(val.textContent)).toBe(10);
  });
});

通用计数器文件:


const Counter = () => {
  const [state, setState] = useState({
    count: 0,
    inpText: '',
  });
  const setNum = (num) => {
    setState((prev) => {
      return {
        ...prev,
        count: prev.count + num,
      };
    });
  };
  const setInp = (e) => {
    setState((prev) => {
      return {
        ...prev,
        inpText: e?.target.value,
      };
    });
  };
  return (
    <>
      <h1
        data-testid='counter-value'
        style={{
          color: 'white',
          position: 'absolute',
          top: '45%',
          left: '50%',
          transform: 'translate(-50%,-60%)',
        }}>
        {state.count}
      </h1>
      <div id='flex'>
        <Button setNum={setNum} plus='+' num={parseInt(state.inpText)} />
        <input data-testid='inp' value={state.inpText} onChange={setInp} />
        <Button setNum={setNum} plus='-' num={-parseInt(state.inpText)} />
      </div>
    </>
  );
};



还有按钮:


const Button = (props) => {
  return (
    <button
      data-testid={`btn-${props.plus}`}
      onClick={() => {
        props.setNum(props.num);
      }}>
      {props.plus}
    </button>
  );
};

【问题讨论】:

  • 如果你正在测试Counter,你不想打电话给render(&lt;Button /&gt;)Buttons 将作为 Counter 渲染的一部分进行渲染。
  • 如何在 Counter 内部引用 Button 组件?我可以将 data-testid 添加到 react 组件吗?
  • 您只需通过data-testids 访问按钮:btn-- & btn-+
  • 我更新了测试文件,以便它从 Counter 组件中获取按钮的 data-testid,但它似乎没有改变任何东西,我得到了完全相同的错误。
  • 我还通过expect(btnPlus).toBeTruthy()检查了btnPlus是否存在,并没有收到错误,但它仍然没有增加值。

标签: javascript reactjs jestjs react-testing-library


【解决方案1】:

我建议避免在 beforeAll/beforeEach 函数中设置初始组件。每个测试用例都应该独立运行,不受其他测试中执行的操作的影响。

相反,使用该逻辑创建一个辅助函数并在每次测试时调用它。

import React from 'react';
import Counter from './Counter';
import { render, fireEvent } from '@testing-library/react';

describe('Counter works', () => {
    let comp;
    let inp;
    let btnPlus;
    let val;
  
    const renderComponent = () => {
        comp = render(<Counter />);
        inp = comp.getByTestId('inp');
        btnPlus = comp.getByTestId('btn-+');
        val = comp.getByTestId('counter-value');
    }

    it('Counter exists', () => {
        renderComponent();
        expect(comp).toBeTruthy();
    });
  
    it('Input works', () => {
        renderComponent();
        expect(inp.value).toBe('');
        fireEvent.change(inp, { target: { value: 10 } });
        expect(inp.value).toBe('10');
        fireEvent.click(btnPlus);
        expect(val.textContent).toBe('10');
    });
});

【讨论】:

  • 感谢您的帮助,它有效,但beforeEach() 不只是做同样的事情并在每个it()test() 之前调用函数吗?
  • 每个测试都应该独立于其他测试运行,但是在您的原始代码中,您在 beforeAll 中进行了设置,这将为 all 测试用例设置组件。虽然您可以使用 beforeEach 代替设置,但在每次测试中调用 renderComponent 会使其更加明确和可读。
猜你喜欢
  • 2020-11-15
  • 2015-03-01
  • 1970-01-01
  • 2017-11-09
  • 2019-04-01
相关资源
最近更新 更多