簡體   English   中英

使用酶進行 JS 單元測試:如何在繼續測試用例之前等待組件方法中的 setState 完成

[英]JS unit testing using enzyme: how to wait for setState within component's method to finish before proceeding with test case

我有一個帶有方法doSomething的組件MyComponent更新狀態,以及基於這些狀態呈現子組件的renderChildren

class MyComponent extends Component {
  constructor(props) {
    super(props);
    ...
    this.state = {
      renderChildA: true,
      renderChildB: false,
    };
  }

  doSomething = (params) => {
    // Do something...

    this.setState({ 
      renderChildA: false,
      renderChildB: true,
    });
  }

  renderChildren = () => {
    const { renderChildA, renderChildB } = this.state;
    if (renderChildA) {
      return <ChildComponentA />;
    } else if (renderChildB) {
      return <ChildComponentB />;
    }
  }

  render() {
    return (
      <div>
        {this.renderChildren()}
        ...
      </div>
    );
  }
}

注意:該組件也連接到 Redux,但已被簡化。

對於單元測試,我調用doSomething並驗證ChildComponentB是否可見:

test('doSomething should trigger ChildComponentB to pop up', () => {
  const wrapper = shallow(
    <MyComponent
    ...
    />,
  ).dive();

  wrapper.instane().doSomething(params); // assume params is defined

  const childComponentB = wrapper.find('ChildComponentB');
  expect(childComponentB).toHaveLength(1);
});

但是,上面的測試用例失敗了:

my-component.test.jsx > Some test group name > doSomething should trigger ChildComponentB to pop up

    expect(received).toHaveLength(length)

    Expected value to have length:
      1
    Received:
      // Some giant JSON object
    recevied.length:
      0

      xxx |    const childComponentB = wrapper.find('ChildComponentB');
      xxx |    expect(childComponentB).toHaveLength(1);
      xxx |  });

根據日志記錄,我看到在測試用例中的expect語句之后觸發了doSomething中的setState 我懷疑這是因為setState是異步的,但我不知道解決方法(除了setTimeout )。

您可以嘗試手動更新組件以獲取最新狀態:

  wrapper.instance().doSomething(params); // assume params is defined
  wrapper.update(); 
  const childComponentB = container.find('ChildComponentB');
  expect(childComponentB).toHaveLength(1);

更多信息: https : //airbnb.io/enzyme/docs/api/ShallowWrapper/update.html

不確定這是否有效,但讓我們嘗試將doSomething函數更新為。

doSomething = (params) => {
  this.setState({ 
    renderChildA: false,
    renderChildB: true,
  },() => this.renderChildren());
}

找到了一個相當簡單的解決方案。 使用Async/Await

test('doSomething should trigger ChildComponentB to pop up', async() => {
  const wrapper = shallow(
    <MyComponent
    ...
    />,
  ).dive();

  await wrapper.instane().doSomething(params);

  const childComponentB = wrapper.find('ChildComponentB');
  expect(childComponentB).toHaveLength(1);
});

只需添加asyncawait

test('describe your test', async() => { // add async here
  const wrapper = shallow(
    <MyComponent
      ...
    />,
  ).dive();

  await wrapper.instane().doSomething(params); // add wait here

  const childComponentB = wrapper.find('ChildComponentB');
  expect(childComponentB).toHaveLength(1)
});
    it('check List component for column list', async () => {
    #ur code for re-render stuff
    await new Promise(resolve => setTimeout(resolve, 0)); // wait for response

    # this will sync ur wrapper with latest tree change
    wrapper = wrapper.update();  
});

暫無
暫無

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

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