2015-08-10 13 views
11

Sto provando a testare un componente che reagisce.Test di reazione; come deridere ComponentDidMount o sovrascriverlo?

var Component = React.createClass({ 

    componentDidMount: function() { 

    return this.setState({ 
     name: 'blabla' 
    }); 
    }, 

    render: function() { 

    return (
     <h1>{this.state.name}</h1> 
    ); 
    } 
}); 

Esiste un modo, durante i test, per deridere ciò che componentDidMount ritorni o lo fa? Questo mi lascerebbe testarlo da solo e testare il comportamento del componente.

Grazie!

+1

Si consiglia di non prendere in giro esso. Se vuoi assicurarti che il tuo componente funzioni, prendi in giro tutto ciò che passi come un sostegno, prendi in giro tutte le dipendenze, ma non prendere in giro il componente stesso. –

+1

Non sono d'accordo. Se OP sta cercando di scrivere test unitari che testano le funzioni all'interno del suo componente, non è affatto insolito per lui voler eliminare altre funzioni che potrebbero influenzare questi test. OP: quale framework di test stai usando? A seconda della tua risposta, potrei avere una soluzione per te. –

+0

Grazie per i tuoi commenti. @ MichaelParker Sto usando karma e moka. –

risposta

1

L'idea, se ho capito bene, è che si sta cercando di spegnere una funzione prima di un componente è reso nel tuo test. Nel tuo caso, componentWillMount viene chiamato solo una volta nel ciclo di vita di un componente, immediatamente prima del rendering del componente. Quindi non puoi semplicemente rendere il componente e quindi lo stub out della funzione,, deve essere fatto prima che il rendering si verifichi.

Prendiamo queste componenti, ad esempio:

parent.js

var Child = require('./child.js'); 
var Parent = React.createClass({ 
    render : function() { 
     return (
      <div className="parent"> 
       <Child/> 
      </div> 
     ); 
    } 
}); 
module.exports = Parent; 

child.js

var Child = React.createClass({ 
    test : function() { 
     return true; 
    }, 
    render : function() { 
     if (this.test) { 
      throw('boom'); 
     } 
     return (
      <div className="child"> 
       Child 
      </div> 
     ); 
    } 
}); 
module.exports = Child; 

Qui, vorremmo spegnere la funzione test prima che il componente Child sia reso, altrimenti, esploderà.

Sono stato in grado di farlo utilizzando jasmine-react. Queste funzioni di supporto forniscono alcune funzionalità utili durante l'esecuzione di test, quasi fino al punto in cui lo TestUtils può essere abbandonato completamente.

jasmineReact.render(component, [container]) esegue il rendering di un'istanza di component nel nodo DOM specificato in [container]. È come TestUtils.renderIntoDocument(), tranne che esegue il rendering del componente in un nodo DOM collegato anziché in un nodo DOM staccato. Effettuerà anche le operazioni di pulizia necessarie al termine del test.

jasmineReact.spyOnClass(componentClass, functionName) interromperà una particolare funzione appartenente a una classe componente. Questo comportamento viene mantenuto fino alla fine del test, il che significa che è possibile chiamare questa funzione prima del in cui viene eseguito il rendering di un componente. Questo, se ho capito bene, è quello che stai cercando.

Quindi, utilizzando queste due funzioni di aiuto, posso scrivere un test per il codice mostrato sopra che sembra qualcosa di simile:

var React = require('react/addons'), 
    Parent = require('./parent.js'), 
    Child = require('./child.js'), 
    jasmineReact = require('jasmine-react-helpers'); 

describe('Parent', function() { 
    it('does not blow up when rendering', function() { 
     jasmineReact.spyOnClass(Child, 'test').and.returnValue(false); 
     var parentInstance = jasmineReact.render(<Parent/>, document.body); //does not blow up 
     expect(parentInstance).toBeTruthy(); //passes 
    }); 
}); 

fatemi sapere se avete domande.

+0

Grazie per questo! 'SpyOnClass(). And.returnValue()' sembra incredibile e piuttosto potente! –

1

Ho trovato due modi per farlo (sono sicuro che ce ne sono altri).

1) Ho usato sinon-chai e richiesto nella classe dell'elemento di base e quindi utilizzare rewireify per mettere un set di una spia sul metodo componentWillMount. Questo funziona, ma non sono sicuro di quale suite di test stai usando.

2) Probabilmente il modo più semplice. È sufficiente utilizzare TestUtils per ottenere un'istanza del componente e quindi eseguire manualmente il metodo componentWillMount.

Questo secondo modo sarebbe probabilmente simile a (perdonate il codice pesudo):

it('should call state when it first mounts', function() { 
    var Component = require('../my-component'); 
    var component = TestUtils.renderIntoDocument(<Component />); 

    component.setState({name: null}); 
    component.componentWillMount(); 

    expect(component.state.name).to.equal('blabla'); 
}); 
+0

Grazie a @badAdviceGuy Ti darò un passaggio e ti faccio sapere –

+2

L'uso di 'TestUtils.renderIntoDocument' attiverà automaticamente' componentWillMount 'funzione. La prima opzione sembra comunque promettente. –

+0

@MichaelParker, sì hai ragione il componenteWillMount verrà eseguito automaticamente, ma poi all'interno del test si ripristina lo stato e si richiama manualmente il metodo e quindi si verifica nuovamente lo stato 'component.componentWillMount()' ecc. – badAdviceGuy

6

Preferisco il seguente approccio, ma richiede l'utilizzo di classi ES6.

// component.jsx 
class Component extends React.Component { 
    componentDidMount() { return this.setState({name: 'blabla'}); } 
    render() { return (<h1>{this.state.name}</h1>); } 
} 

//component-spec.jsx 
describe('Component',() => { 
    it('does stuff',() => { 
     let ComponentTest = class extends Component { 
      componentDidMount() { 
       // your override here 
      } 
     }; 
     let component = TestUtils.renderIntoDocument(<ComponentTest />); 
     //expect(component...).toEqual(...) 
    }); 
}); 

Il punto è quello di creare un su richiesta ChildClass ereditare l'OriginalClass, fare tutto ciò che ha la precedenza e quindi TestUtils.renderIntoDocument(<ChildClass />)

Problemi correlati