亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何測試分派 Redux / Thunk 操作的 React 組件

如何測試分派 Redux / Thunk 操作的 React 組件

鳳凰求蠱 2021-12-23 19:44:01
我正在為一個組件編寫集成測試,該組件應該根據異步(thunk)redux 操作的響應重定向到特定路徑。這是我的組件的簡化版本:class MyComponent extends React.Component {  constructor(props) {    super(props);    this.state = {      redirect: false    }    this.props.dispatch(asyncThunkAction())      .then( () => this.setState({redirec: true}) )      .catch( (err) => console.log('action failed') )  } ...  render() {    if (this.state.redirect) {      return <Redirect to='/whocares' />    }    ...  }}function mapStateToProps(state) {  return {     ...  };}export default connect(mapStateToProps)(MyComponent);我想編寫一個測試,斷言組件重定向到預期路徑。我正在使用這種技術來檢查實際的重定向路徑(它并不完美,但不是這個問題的重點)。我卡住的地方是.then()下面 redux/thunk 動作中的狀態變化。因為這是一個承諾,重定向發生在我的expect聲明之后,所以我無法測試。這是我的測試的樣子:const middlewares = [thunk];const mockStore = configureStore(middlewares);  test('redirects after thunk action', () => {    const redirectUrl = '/whocares'    const data = {};    jest.mock('../actions');    act(() => {      ReactDOM.render(        <TestRouter            ComponentWithRedirection={<MyComponent store={mockStore(data)} />}            RedirectUrl={redirectUrl}        />,         container);    });    expect(container.innerHTML).toEqual(      expect.stringContaining(redirectUrl)    )  })我的 TestRouter 只是將預期的重定向 URL 打印到 DOM 中。(查看上面的鏈接以獲取有關此 hack 的完整說明。)因此,現在我的測試(正確)識別了在 thunk 操作進行時出現的加載屏幕,而不是到達預期的路線。我認為這樣做的正確方法是模擬響應,asyncThunkAction以便它返回具有匹配數據的已解決承諾,但到目前為止我還沒有弄清楚如何做到這一點。我按照手動模擬的 Jest 文檔創建了相應的模擬文件:// __mocks__/actions.jsconst asyncThunkAction = function(){    return Promise.resolve({foo: 'bar'});};export { asyncThunkAction };...但我的測試仍然“看到”加載狀態。我什至不認為它正在查看我的模擬文件/操作。這樣做的正確方法是什么?
查看完整描述

2 回答

?
牛魔王的故事

TA貢獻1830條經驗 獲得超3個贊

這是我如何讓這個工作的“食譜”......


使用測試庫/反應...


import { render, fireEvent, waitForElement, act } from '@testing-library/react';

(+1 給@tmahle 這個建議)


通過創建“手動模擬”來模擬 axios(或者在我的情況下是包裝它的 API 模塊),這基本上需要__mocks__在包含同名文件的真實文件旁邊創建一個目錄。然后導出一個具有替換get方法(或您的代碼使用的任何一個)的屬性的對象。


//__mocks__/myclient.js

export default {

  get: jest.fn(() => Promise.resolve({ data: {} }))

};

即使您不在測試中調用模擬代碼,您也需要import在測試文件中調用它...


import myapi from '../api/myapi';

jest.mock('../api/myai');

您可以模擬來自模擬 API 調用的響應,如下所示:


myapi.get.mockResolvedValueOnce({

  data: { foo: "bar" },

});

我對這部分有點模糊......即使模擬的 API 請求立即以已解決的承諾響應,您可能需要wait編寫expects


const { getByText, getByTestId, container } = render(<MyComponent />);

await wait(() => getByText('Some text that appears after the '));

expect(container.innerHTML).toEqual('whatever');

所有這些都在各種文檔和 SO 問題中“出現在那里”......但我花了很長時間才把它們拼湊在一起。希望這可以節省您的時間。


查看完整回答
反對 回復 2021-12-23
?
回首憶惘然

TA貢獻1847條經驗 獲得超11個贊

誠然,這是對您的問題的一個側面回答,但我建議您嘗試使用 testing-library 及其所體現的理想,尤其是對于集成測試。

它在 DOM 和 React 兩種風格中都可用,使用哪一種可能取決于您的重定向發生在什么抽象級別:

https://github.com/testing-library/dom-testing-library https://github.com/testing-library/react-testing-library

使用此范例,您不會嘗試斷言用戶被重定向到正確的路徑,而是在重定向后屏幕上顯示正確的內容。您還可以將您的模擬限制在絕對必要的范圍內(如果您正在進行真正的集成測試,則您的測試環境無法模擬的可能沒有或只有瀏覽器 API)。

這里的整體方法可能會讓你模擬更少,并且可能渲染應用程序的更大部分。一個可能有用的例子可以在這里找到:https : //codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/master/?fontsize=14&module=%2Fsrc%2F__tests__%2Freact -router.js&previewwindow=tests

由于這種方法中的嘲諷較少,因此您如何實現這一點的具體細節可能超出了您所提供示例的范圍,但上面的示例鏈接應該對入門有很大幫助。


查看完整回答
反對 回復 2021-12-23
  • 2 回答
  • 0 關注
  • 175 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號