0
說我有下列包裝部件:測試異步嵌套組件
'use strict'
import React, {PropTypes, PureComponent} from 'react'
import {update} from '../../actions/actions'
import LoadFromServerButton from '../LoadFromServerButton'
import {connect} from 'react-redux'
export class FooDisplay extends PureComponent {
render() {
return (
<p>
<span className='foo'>
{this.props.foo}
</span>
<LoadFromServerButton updateFunc={this.props.update} />
</p>
)
}
}
export const mapStateToProps = (state) => {
return {foo: state.foo.foo}
}
FooDisplay.propTypes = {
foo: PropTypes.string
}
export const mapDispatchToProps = (dispatch) => {
return {
update: (foo) => dispatch(update(foo))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(FooDisplay)
和下面的內部部件:
'use strict'
import React, {PropTypes, PureComponent} from 'react'
import {get} from '../../actions/actions'
import ActiveButton from '../ActiveButton'
import {connect} from 'react-redux'
export class LoadFromServerButton extends PureComponent {
doUpdate() {
return this.props.get().then(this.props.updateFunc)
}
render() {
return (
<ActiveButton action={this.doUpdate.bind(this)} actionArguments={[this.props.foo]} text='fetch serverside address' />
)
}
}
export const mapStateToProps = (state) => {
return {foo: state.foo.foo}
}
export const mapDispatchToProps = (dispatch) => {
return {
get:() => dispatch(get())
}
}
LoadAddressFromServerButton.propTypes = {
updateFunc: PropTypes.func.isRequired
}
export default connect(mapStateToProps, mapDispatchToProps)(LoadFromServerButton)
ActiveButton
是圍繞一個按鈕的非常薄的包裝用一個onclick和參數解構。
現在讓我們說,我我得到的動作寫如下:如果我寫一個測試,像這樣
export const get =() => dispatch => http('/dummy_route')
.spread((response, body) => dispatch(actOnThing(update, body)))
現在:
/* global window, test, expect, beforeAll, afterAll, describe */
'use strict'
import React from 'react'
import FooDisplay from './index'
import {mount} from 'enzyme'
import {Provider} from 'react-redux'
import configureStore from '../../store/configureStore'
import nock, {uriString} from '../../config/nock'
import _ from 'lodash'
const env = _.cloneDeep(process.env)
describe('the component behaves correctly when integrating with store and reducers/http',() => {
beforeAll(() => {
nock.disableNetConnect()
process.env.API_URL = uriString
})
afterAll(() => {
process.env = _.cloneDeep(env)
nock.enableNetConnect()
nock.cleanAll()
})
test('when deep rendering, the load event populates the input correctly',() => {
const store = configureStore({
address: {
address: 'foo'
}
})
const display = mount(<Provider store={store}><FooDisplay /></Provider>,
{attachTo: document.getElementById('root')})
expect(display.find('p').find('.address').text()).toEqual('foo')
const button = display.find('LoadFromServerButton')
expect(button.text()).toEqual('fetch serverside address')
nock.get('/dummy_address').reply(200, {address: 'new address'})
button.simulate('click')
})
})
這導致:
Unhandled rejection Error: Error: connect ECONNREFUSED 127.0.0.1:8080
經過一番思考之後,這是由於測試沒有返回承諾,因爲按鈕點擊導致e承諾引擎蓋下,因此,afterAll
馬上運行,清理nock,並通過真正的http連接通過電線。
我該如何測試這種情況?我似乎沒有一個簡單的方法來返回正確的承諾......我如何測試從這些更新產生的DOM更新?
好像你不是用拒絕承諾處理,但只有當它滿足了。你是否打算模擬一個離線環境?如果刪除nock.disableNetConnect()及其對應部分,會發生什麼情況?如果您的測試正在執行任何異步操作,則應該包含done參數並在異步操作完成時調用它。作爲替代方案,您也可以返回測試承諾。請參閱https://facebook.github.io/jest/docs/asynchronous.html – nbkhope
是的我不明白,但我怎樣才能返回正確的承諾?按鈕點擊會觸發一個異步操作,但我不清楚如何強制從測試返回正確的測試 –
「更新」功能的定義在哪裏?我覺得this.props.getFoo()應該是this.props.get(),在LoadFromServerButton的doUpdate函數中? – nbkhope