2017-06-08 40 views
4

我想測試一個運行一些異步代碼並調用componentDidMount中的setState的React組件。如何在用酶測試時等待componentDidMount中的setState解決?

這裏是我的反應,我想測試組件:

/** 
* 
* AsyncComponent 
* 
*/ 

import React from 'react'; 

class AsyncComponent extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     loaded: false, 
     component: null, 
    }; 
    } 
    componentDidMount() { 
    this.props.component.then(component => { 
     this.setState({ 
     loaded: true, 
     component: component.default ? component.default : component, 
     }); 
    }); 
    } 
    render() { 
    if (!this.state.loaded) { 
     return null; 
    } 

    const Component = this.state.component; 

    const { component, ...rest } = this.props; 

    return <Component {...rest} />; 
    } 
} 

export default AsyncComponent; 

下面是測試案例。我用笑話和酶。

import React from 'react'; 
import { mount } from 'enzyme'; 

import AsyncComponent from '../index'; 

const TestComponent =() => <div>Hello</div>; 

describe('<AsyncComponent />',() => { 
    it('Should render loaded component.',() => { 
    const promise = Promise.resolve(TestComponent); 
    const rendered = mount(<AsyncComponent component={promise} />); 
    expect(rendered.state().loaded).toBe(true); 
    }); 
}); 

測試失敗,因爲state.loaded仍設置爲false。有沒有一種方法可以確保AsyncComponent在調用expect之前完全加載?

我可以讓它工作,如果我在setTimeout中包裝預期的斷言,但這似乎是一個相當hacky的方式來做到這一點。我應該如何去做這件事?

回答

-1

則需要由使用async/await通知有關承諾玩笑或返回從測試的承諾,看看在docs

describe('<AsyncComponent />',() => { 
    it('Should render loaded component.', async() => { 
    const promise = Promise.resolve(TestComponent); 
    const rendered = mount(<AsyncComponent component={promise} />); 
    await promise 
    expect(rendered.state().loaded).toBe(true); 
    }); 
}); 
+0

我試着用你的代碼,但測試失敗,「rendered.state() .loaded「仍然等於false。 –

+0

你能否檢查一下該承諾中的回調是否被調用? –

+0

'Promise.resolve(TestComponent)'立即與組件一起解析。它與'setState'無關並且組件已準備好進行測試。這段代碼沒有任何意義,當然也不能解決上述問題。 –

0

我遇到同樣的問題,我想出了一些笨拙解決方案,我有一些componentDidMount函數調用,我想檢查是否該函數被調用,因此代碼爲我工作

const loadFiltersTree = jest.fn() 
const wrapper = shallow(<FilterTree loadFiltersTree={loadFiltersTree} />) 
jest.useFakeTimers() 
jest.runAllTimers() 
setImmediate(() => { 
    expect(loadFiltersTree.mock.calls.length).toEqual(1) 
})