2017-05-30 70 views
1

我正在使用create-react-app,jest和酶。如何在React中的類組件的實例方法中獲取模擬?

我有一個類組件加載「細節」數據單擊錶行的時候,那麼在細節可以編輯和保存一個模式顯示形式:

import React, { Component } from "react"; 
import fetch from "isomorphic-fetch"; 
import Modal from "./Modal"; 

export default class RecordViewer extends Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     showModal: false, 
     currentRecord: {} 
    }; 
    } 

    open(id) { 
    fetch(`api/${id}`) 
     .then(res => res.json()) 
     .then(data => { 
     this.setState({ 
      ...this.state, 
      currentRecord: data.record, 
      showModal: true 
     }); 
     }); 
    } 

    render() { 
    <div> 
     <Modal visible={this.state.showModal} contents={this.state.currentRecord} /> 
     <table> 
     <tr onClick={()=>this.open(1)}> 
      <td>Record Overview for Item 1</td> 
     </tr> 
     </table> 
    </div> 
    } 
} 

我想嘲笑獲取函數以確定它是否被調用,但也只是爲了防止組件試圖擊中API。例如,我想測試傳遞給模態的內容。

傳遞fetch作爲道具會讓這個變得容易,但是這個組件的父項需要知道它,這似乎沒有道理。

有沒有一種方法來嘲笑這個設置的提取?

也許有更好的方法去完成這個測試呢?

回答

2

其實你應該創建一個「容器」組件來連接業務規則和「查看」前;

src/components 
    -> RecordViewer.js 
    -> RecordViewerContainer.js 

因此,在RecordViewer.js你可以做一個純組分至極只是導出回調函數前。

RecordViewer.js

import React, { Component } from "react"; 
import Modal from "./Modal"; 

class RecordViewer extends Component { 
    render() { 
    <div> 
     <Modal visible={this.props.showModal} 
     contents={this.props.currentRecord} /> 
     <table> 
     <tr onClick={() => this.props.onOpen(1)}> 
      <td>Record Overview for Item 1</td> 
     </tr> 
     </table> 
    </div> 
    } 
} 

RecordViewer.propTypes = { 
    showModal: React.PropTypes.bool, 
    onOpen: React.PropTypes.func, 
    currentRecord: React.PropTypes.object 
} 

RecordViewer.defaultProps = { 
    showModal: false, 
    currentRecord: {}, 
    onOpen: function(){} 
} 

export default RecordViewer; 

RecordViewerContainer.js

import React, { Component } from "react"; 
import fetch from "isomorphic-fetch"; 
import RecordViewer from "./RecordViewer"; 

export default class RecordViewerContainer extends Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     showModal: false, 
     currentRecord: {} 
    }; 
    } 

    open(id) { 
    fetch(`api/${id}`) 
     .then(res => res.json()) 
     .then(data => { 
     this.setState({ 
      ...this.state, 
      currentRecord: data.record, 
      showModal: true 
     }); 
     }); 
    } 

    render() { 
    <RecordViewer currentRecord={this.state.currentRecord} showModal={this.state.showModal} /> 
    } 
} 

然後你可以嘲笑的成分PARAMS和分離API調用和業務規則。

小貼士:我們有更好的工具,比如redux,altjs,reflux(flux的實現)。

+0

這個組件是一個redux容器,實際上,我只是簡化了它來解決我的問題。無論如何,看起來它需要一點重構。我有點不清楚本地國家應該與Redux商店相比,但有一點研究[我發現這個](https://github.com/reactjs/redux/issues/1287)。 RecordViewer將保持表單狀態,因此將它保持在本地可能有意義?無論如何,感謝幫助我思考這件事! – user6689821

1

有一種方法,但它並不理想。看看fetch-mock包。

它不理想的原因是你不會完全隔離你的組件,所以在技術上它不會再是單元測試,但是你沒有指定你正在寫什麼類型的測試。

+0

我在寫單元測試。我應該說!感謝這個軟件包,它看起來非常有用。我認爲重構是我目前的情況所要求的。 – user6689821

相關問題