簡體   English   中英

具有異步功能的有狀態React組件未通過Jest測試

[英]Stateful React component with async function failing Jest test

我正在這里關注Pluralsight的Jest測試教程 我編寫的代碼與作者完全一樣,但出於某種原因我的測試沒有通過。

我對作者回購的請求: https//github.com/danielstern/isomorphic-react/pull/19

我有一個簡單的React組件,它通過對componentDidMount的服務的異步/等待調用來更新它的count狀態。

{this.state.count != -1 ? `${this.state.count} Notifications Awaiting` : 'Loading...'}

預期

由於我已經模擬了NotificationsService,並將count設置為42 ,因此測試應該在組件內傳遞"42 Notifications Awaiting!"

結果

文本仍然卡在默認Loading...

我已經正確地模擬了服務,並且count變量甚至被正確記錄為42 但是this.state.count仍為-1因此不顯示: ${this.state.count} Notifications Awaiting它的${this.state.count} Notifications Awaiting仍然顯示Loading...因此測試失敗。


我試過的

1)我嘗試在延遲中添加1000。

2)在測試中使用setTimeout嘗試。

3)嘗試了jest.useFakeTimers(); jest.runAllTimers();

但是沒有任何工作,即使count設置為42,組件內部的count仍然保持在-1 。在我看來,我的測試在狀態完成設置之前運行了嗎?

在此輸入圖像描述

NotificationsViewser.jsx組件

import React from 'react';
import NotificationsService from '../services/NotificationsService';

export default class componentName extends React.Component {
  constructor(...args) {
    super(...args);

    this.state = {
      count: -1
    }
  }

  async componentDidMount () {
    let { count } = await NotificationsService.GetNotifications();
    console.log('count:', count);
    this.setState({
      count
    });
  }

  componentDidUpdate() {
    console.log('componentDidUpdate:', this.state);
  }

  render() {
    return (
      <div className="mt-3 mb-2">
        <div className="notifications">
          {this.state.count != -1 ? `${this.state.count} Notifications Awaiting` : `Loading...`}
        </div>
      </div>
    )
  }
}

NotificationsService.js

import { delay } from 'redux-saga';

export default {
  async GetNotifications() {
    console.warn("REAL NOTIFICATION SERVICE! CONTACTING APIS!");

    await delay(1000);
    return { count: 42 };
  }
}

mocks :NotificationsService.js

let count = 0;

export default {
  __setCount(_count) {
    count = _count;
  },
  async GetNotifications() {
    console.warn("GOOD JOB! USING MOCK SERVICE");
    return { count };
  }
}

最后...

考試

import React from 'react';
import renderer from 'react-test-renderer';
import delay from 'redux-saga';

import NotificationsViewer from '../NotificationsViewer';

jest.mock('../../services/NotificationsService');

const notificationService = require('../../services/NotificationsService').default;

describe('The notification viewer', () => {

  beforeAll(() => {
    notificationService.__setCount(42);
  });

  it('should display the correct number of notifications', async() => {
    const tree = renderer
      .create(
        <NotificationsViewer/>
      );

    await delay();

    const instance = tree.root;
    const component = instance.findByProps({className: `notifications`});
    const text = component.children[0];
    console.log('text is:', text);

    expect(text).toEqual('42 Notifications Awaiting!');
  });
})

問題是await delay()不能讓所有React生命周期方法像componentDidMount實例化/被調用。

我不得不使用Enzyme ,盡管由於很多開放的bug問題,作者沒有推薦它。

使用Enzyme我可以確保調用componentDidMount ,從而使用模擬服務將count的狀態設置為42

我還需要安裝以下軟件包:

"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",

固定測試

import React from 'react';
import renderer from 'react-test-renderer';
import Adapter from 'enzyme-adapter-react-16';
import { shallow, configure } from 'enzyme';

configure({adapter: new Adapter()});

import NotificationsViewer from './NotificationsViewer';

jest.mock('../services/NotificationsService');

const notificationService = require('../services/NotificationsService').default;

notificationService.default = jest.fn();

describe('The notification viewer', () => {

  beforeAll(() => {
    notificationService.__setCount(42);
  });

  // it('pass', () => {});

  it('should display the correct number of notifications', async() => {
    const tree = renderer.create(<NotificationsViewer />);
    const wrapper = shallow(<NotificationsViewer />);
    const instance = tree.root;

    await wrapper.instance().componentDidMount();

    const component = instance.findByProps({className: `notifications`});
    const text = component.children[0];
    console.log('text is:', text);

    expect(text).toEqual('42 Notifications Awaiting');
  });
})

在此輸入圖像描述

實際上,真正的問題是在isomorphic-react/src/components/__tests__/NotificationsViewer.js文件中。 delay是以錯誤的方式導入的,這導致測試時出錯。

如果像這樣導入delayimport { delay } from 'redux-saga'修復問題。 = d

也許你的describe也需要是一個異步函數? 需要在async范圍內聲明await語句,不是嗎?

暫無
暫無

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

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