2016-07-12 5 views
3

Ich verwende Enzym/Mokka, um meine reagierende Komponente zu testen.Enzym/Mocha: So testen Sie eine Reaktionskomponente Funktion durch Auslösen eines OnChange-Ereignisses von einer untergeordneten Komponente

Ich habe eine Elternkomponente, die ich testen.

let wrapper = mount(<Parent />); 

und dieser Elternteil hat eine untergeordnete Komponente darin Funktion ist machen

render: function() { 
    <Child onChange={this.foo} /> 
}, 
foo: function() { 
    console.log("I was called"); 
} 

Ich würde das onChange Funktion des Kindes wie so abzufeuern, dass ich meine Eltern foo Funktion testen kann.

Bis jetzt habe ich keine Möglichkeit gefunden, dies zu tun - ich habe über Sinon und Stubbing gelesen, aber das ist hauptsächlich über Abfangen von Funktionen und nicht feuern sie.

Der folgende Test

shallow(<Parent />).instance().foo(); 

ist ein schwacher Test, weil es nicht die Codezeile testet mein Kind und Eltern verbinden, und für den Fall, habe ich nicht einen Komponententest für mein Kind geschrieben, es testet die OnChange-Funktion des Kindes auch nicht. IMHO - Wenn meine Komponenten Eltern/Kinder bedeutet weniger Testbarkeit Zerschlagung - dann ist etwas falsch mit diesem Rahmen

Jede Hilfe geschätzt wird, dank

+0

Wenn Sie die 'foo testen()' Methode in den Elterntests und die Fähigkeit des Kindes auslösen 'props.onChange()' (mit 'sinon.spy()') in den Kinder Tests, dann IMO Sie don Ich muss nicht testen, dass React 'this.foo' aufrufen kann, wenn das Kind' props.onChange' aufruft. Genauso wie Sie nicht testen müssen, dass React 'rendern' ('' '' ''' '' '' '' '' '' '' '' '' '' '' '' '' '' 'Requisiten' 'oder' 'componentWillReceiveProps()'' repliziert. –

Antwort

8

Dies ist etwas, was ich in vielen meiner Tests mache. Die Methode, die für mich am besten funktioniert, ist, den Handler der untergeordneten Komponente onChange manuell aufzurufen und Ihre Assertionen basierend auf dem erwarteten Verhalten zu erstellen.

Also lassen Sie uns sagen, dass Sie eine übergeordnete Komponente haben, die wie folgt aussieht:

import React from 'react'; 
import Child from './child'; 

export default class extends React.Component { 
    render() { 
     return (
      <div> 
       <Child onChange={this.foo} /> 
      </div> 
     ); 
    } 

    foo() { 
     console.log('bar'); 
    } 
} 

Die onChange prop bestanden Kind wird die Zeichenfolge ‚bar‘ protokollieren, wenn aufgerufen. Dies ist das Verhalten, das wir testen möchten. Um dies zu tun, müssen wir die folgenden Schritte unternehmen:

  1. Stub console.log Ihre spöttische Bibliothek der Wahl mit (Ich werde für dieses Beispiel Sinon verwenden)

  2. Erstellen Sie eine flache Instanz die übergeordnete Komponente, und erhalten Sie einen Verweis auf seine Child.

  3. Sie manuell die onChange Stütze des Kindes berufen.

  4. behaupten, dass console.log einmal genannt wurde, und mit einem einzigen Argument: 'bar'

Und hier ist, wie ich das tun würde (mit Mokka und chai):

import Foo from './foo'; 

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

import sinon from 'sinon'; 
import sinonChai from 'sinon-chai'; 
import chai, {expect} from 'chai'; 

describe('Foo',() => { 
    let renderedElement; 

    function renderComponent() { 
     const componentElement = React.createElement(Foo); 

     renderedElement = shallow(componentElement); 
    } 

    before(() => { 
     chai.use(sinonChai); 
    }); 

    it('should log the string "bar" when the child component is changed',() => { 
     //step 1 
     sinon.stub(console, 'log'); 

     //step 2 
     renderComponent(); 
     const childComponent = renderedElement.props().children; 

     //step 3 
     childComponent.props.onChange(); 

     //step 4 
     expect(console.log).to.have.callCount(1); 
     expect(console.log).to.be.calledWith('bar'); 

     //clean up 
     console.log.restore(); 
    }); 
}); 

der Grund, warum ich diesen Ansatz mag, ist, weil es Verhalten Komponente testen im Gegensatz zu einfach testen, dass sie eine Funktion als Stütze übergeben wurde, die auf eine andere Funktion, um gleich passiert.

0

Versuchen Sie Ihre Tests in Teile zu brechen. Zum Beispiel ...

Zum einen Test, dass die erwartete Funktion, um Ihr Kind-Komponente übergeben wurde:

import { shallow } from 'enzyme'; 

const actual = shallow(<Parent />); 
const expected = <Child onChange={actual.instance().foo} /> 

expect(actual.matchesElement(expected)).true; 

ich über den einfachen matchesElement Ansatz verwenden möchten, wenn es wenig in der Komponente gerendert wird ich bin Testen, aber Sie könnten auch einen find Selektor verwenden, um die Child Instanz zu finden und dann zu testen.

testen Sie dann Ihre foo Funktion separat:

import { shallow } from 'enzyme'; 

const actual = shallow(<Parent />).instance().foo(); 
const expected = 'expected return of foo' 

expect(actual).equals(expected); 

Sie können Ihre Child Komponente separat testen und wie sie es Griffe onChange prop.

auch betrachten:

Einige der Wesen hier verwendet, die Enzym-API

+0

Dies ist keine schlechte Idee, aber im Allgemeinen seine nicht testen Funktionalität, seine Vergleich Strings. Was ist der Unterschied zwischen Übereinstimmungen und der einfachen Überprüfung, dass die Renderfunktion nicht bei jedem Commit geändert wurde? Außerdem enthält Parent ungefähr 10 Komponenten, und ich vereinfachte die Frage. – NiRR

+0

meinen Kommentar unter dem Beispiel Siehe: für jeden komplex macht es besser ist, die 'find' api zu verwenden, um das Kind zu finden und zu behaupten, es wie erwartet eingerichtet wurde. – ctrlplusb

Verwandte Themen