簡體   English   中英

更新未包含在 act(...) 中,並且模擬 function 未觸發。 反應測試庫,開玩笑

[英]Update not wrapped in act(…) and the mock function not firing. react-testing-library, jest

我希望得到一些幫助。 我一直在研究它太久,認為沒有提出問題。

提前感謝您的時間和關注,

我已經搜索了互聯網並嘗試了很多東西,但我仍然沒有運氣 - 這就是問題所在。

總而言之-我正在關注https://kentcdodds.com/blog/fix-the-not-wrapped-in-act-warning

將 react-testing-library 與 jest 結合使用 - 並遇到兩個問題

  1. Warning: An update to Login inside a test was not wrapped in act(...).
  2. 開玩笑並沒有意識到正在調用模擬

我真的認為我已經正確連接了所有東西 - 不確定我錯過了什么。 在模擬里面我可以放一個 console.log 並且可以確認模擬確實被調用了。

/*
  Test
*/
it('should call props.fetchSignIn with the username and password', async () => {
  const promise = Promise.resolve({
    email: 'test@circulate.social',
    firstName: 'Mike',
    lastName: 'A',
  });
  const fetchSignIn = jest.fn(() => promise);
  const { queryByTestId, queryByPlaceholderText } = renderLogin({
    fetchSignIn,
  });
  const emailInput = queryByPlaceholderText('joedoe@gmail.com');
  const passwordInput = queryByPlaceholderText('password');
  const submitButton = queryByTestId('submitButton');

  fireEvent.change(emailInput, {
    target: { value: 'mike@circulate.social' },
  });
  fireEvent.change(passwordInput, { target: { value: 'Password1!' } });

  fireEvent.click(submitButton);

  // I expected this to fail from the parameters being wrong
  expect(fetchSignIn).toHaveBeenCalledWith('asf');

  await act(() => promise);
});
/*
  Functional Component using the `useState(...)` hooks
  onFormFinished is the form `onSubmit` handler
*/
  const handleSignIn = async (
    email: string,
    password: string
  ): Promise<UserContextType['user']> => {
    setIsLoginInFlight(true);
    try {
      const result = await props.fetchSignIn(email, password);
      setIsLoginInFlight(false);
      return result;
    } catch (error) {
      // Other logic removed
  };

  const onFormFinish = async (values: FormValues): Promise<void> => {
    const { email, password } = values;
    const signInResult = await handleSignIn(email, password);

    // Other logic removed
  };

發生了兩件事 1 - 警告 2 - 測試失敗,因為fetchSignIn從未被調用

預期結果 由於調用了fetchSignIn而導致測試失敗,但參數錯誤

歡迎任何意見或要求澄清。

謝謝

我在提交 forms 和 Ant 設計 4 + react-testing-library 時也遇到了一些麻煩。 經過一些實驗后,我始終使用 data-testid 提交 forms:

<Button data-testid="submit" htmlType="submit">Submit</>

// Form element has onFinish attribute

// in test
fireEvent.click(rtl.getByTestId("submit"));
expect(...);

這不是 RTL 所提倡的(應避免使用 datat-testid,像真正的用戶一樣進行測試),但我可以接受。

但是根據https://github.com/ant-design/ant-design/issues/21272觸發提交事件應該也可以,我一定會試一試。

與喜劇接壤,絕對不是解決問題的正確方法。 但是一種解決問題的方法 - 除了完全避免使用onFinish並依賴按鈕上的onClick之外,唯一對我有用的方法。

那么訣竅實際上是將expect(...)包裝在setTimeout(...)

      // click || submit - both seemed to work for me
      fireEvent.submit(submitButton);
      setTimeout(() => {
        expect(fetchSignIn).toHaveBeenCalledWith('asf');
      });
    it('should call props.fetchSignIn with the username and password', async () => {
      const promise = Promise.resolve({
        email: 'test@circulate.social',
        firstName: 'Mike',
        lastName: 'A',
      });
      const fetchSignIn = jest.fn(() => promise);
      const { queryByTestId, queryByPlaceholderText } = renderLogin({
        seedEmail: 'aasdf',
        seedPassword: 'asdf',
        fetchSignIn,
      });
      const emailInput = queryByPlaceholderText('joedoe@gmail.com');
      const passwordInput = queryByPlaceholderText('password');
      const submitButton = queryByTestId('submitButton');

      fireEvent.change(emailInput, {
        target: { value: 'mike@circulate.social' },
      });
      fireEvent.change(passwordInput, { target: { value: 'Password1!' } });

      // click || submit - both seemed to work for me
      fireEvent.submit(submitButton);
      setTimeout(() => {
        expect(fetchSignIn).toHaveBeenCalledWith('asf');
      });

      await act(() => promise);
    });

這是有人在 GitHub 問題https://github.com/ant-design/ant-design/issues/21272#issuecomment-628607141上向我提出的,所以在 GH 上向 @ildarnm 大喊

讓我們先解決您的第二個問題。

開玩笑並沒有意識到正在調用模擬

我發現使用 ant 設計 forms 進行測試也很棘手。 經過一些挖掘和實驗,似乎模擬“點擊”不會觸發 onFinish,而是模擬“提交”。 使用 Jest 和 Enzyme 對以下示例進行成像:

export default MyForm = () => {
    <Form onFinish={onFinish}>
       <Form.Item>
         <Button htmlType='submit'>Submit</Button>
       </Form.Item>
    </Form>
}

it('should trigger onFinish if submit', () => {
   const onFinish = jest.fn();
   const wrapper = mount(<MyForm onFinish={onFinish}/>);
   wrapper.find('button').simulate('submit');
   await sleep(200)
   expect(onFinish).toHaveBeenCalled();
})

我自己也在為第一個問題苦苦掙扎:

警告:測試中登錄的更新未包含在 act(...) 中

請注意,只有在出現驗證錯誤時才會發生這種情況,因為在它們的表單實現中存在內部 state 更改。

首先,這是一個警告,意思是如果你不介意日志被污染可以忽略它。

其次,只有在“開發”而不是“生產”時才發出警告。

如果你確實想讓它消失,這就是我正在采取的“hacky”方式(我不知道是否有更好的方式):

it('should trigger onFinish if submit', () => {
   const onFinish = jest.fn();
   const wrapper = mount(<MyForm onFinish={onFinish}/>);
   await act(async () => {
     wrapper.find('button').simulate('submit');
   })
   await sleep(200)
   wrapper.update()
   // check errors here
   expect(onFinish).not.toHaveBeenCalled();
})

這在這里正式記錄: https://github.com/enzymejs/enzyme

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM