2015-08-10 4 views
11

Ich versuche eine Reaktionskomponente zu testen.Reaktionstest; wie man componentDidMount vortäuscht oder es überschreibt?

var Component = React.createClass({ 

    componentDidMount: function() { 

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

    render: function() { 

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

Gibt es eine Möglichkeit, während des Tests, zu verspotten, was componentDidMount zurückkehrt oder tut? Das würde mich dazu bringen, es selbst zu testen und nur das Renderverhalten der Komponenten zu testen.

Danke!

+1

Sie sollten es nicht verspotten. Wenn du sicherstellen willst, dass deine Komponente funktioniert, spotte alles, was du ihr als Requisite übergibst, spotte alle Abhängigkeiten, aber verspotte die Komponente selbst nicht. –

+1

Ich stimme nicht zu. Wenn OP versucht, Komponententests zu schreiben, die Funktionen innerhalb seiner Komponente testen, ist es nicht ungewöhnlich für ihn, andere Funktionen auszugeben, die diese Tests beeinflussen könnten. OP - Welchen Testrahmen verwendest du? Abhängig von Ihrer Antwort könnte ich eine Lösung für Sie haben. –

+0

Danke für Ihre Rückmeldungen. @MichaelParker Ich benutze Karma und Mokka. –

Antwort

1

Die Idee hier, wenn ich richtig verstehe, ist, dass Sie eine Funktion Stub sind versucht, bevor eine Komponente gerendert in Ihrem Test. In Ihrem Fall wird componentWillMount nur einmal im Lebenszyklus einer Komponente aufgerufen, unmittelbar bevor die Komponente gerendert wird. So können Sie nicht nur die Komponente und dann die Funktion ausgeben, es muss getan werden, bevor das Rendern auftritt.

wir diese Komponenten zum Beispiel nehmen:

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; 

Hier wollen wir die test Funktion Stub bevor unsere Child-Komponente gerendert wird, sonst wird sie explodieren.

Ich konnte dies mit jasmine-react tun. Diese Hilfsfunktionen bieten einige nützliche Funktionen beim Ausführen von Tests, fast bis zu dem Punkt, an dem TestUtils vollständig gelöscht werden kann.

jasmineReact.render(component, [container]) rendern eine Instanz von component in den DOM-Knoten, der in [container] angegeben ist. Dies ist wie TestUtils.renderIntoDocument(), außer dass die Komponente in einen angehängten DOM-Knoten anstelle eines gelösten DOM-Knotens umgewandelt wird. Es führt auch die notwendigen Reinigungsvorgänge durch, wenn der Test beendet ist.

jasmineReact.spyOnClass(componentClass, functionName) wird eine bestimmte Funktion ausstechen, die zu einer Komponentenklasse gehört. Dieses Verhalten wird bis zum Ende des Tests beibehalten, dh Sie können diese Funktion aufrufen, bevor eine Komponente gerendert wird. Wenn ich das richtig verstehe, ist das, wonach Sie suchen.

Also, diese beiden Hilfsfunktionen verwendet wird, kann ich einen Test für die darüber sieht wie folgt aus etwas gezeigt Code schreiben:

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 
    }); 
}); 

Lassen Sie mich wissen, wenn Sie Fragen haben.

+0

Danke dafür! Die 'spyOnClass(). And.returnValue()' sieht erstaunlich und ziemlich mächtig aus! –

1

Ich habe zwei Möglichkeiten gefunden (ich bin mir sicher, dass es mehr gibt).

1) Ich habe sinon-chai verwendet und in der Basiselementklasse benötigt und dann rewireify verwendet, um einen Spion auf die componentWillMount-Methode zu setzen. Dies funktioniert aber nicht sicher, welche Test-Suites Sie verwenden.

2) Wahrscheinlich der leichtere Weg. Verwenden Sie einfach die TestUtils, um eine Instanz der Komponente abzurufen, und führen Sie dann einfach die componentWillMount-Methode manuell aus.

Das zweite Weg wäre wahrscheinlich in etwa so aussehen (verzeihen Sie den pesudo Code):

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

Danke @badAdviceGuy Ich werde es versuchen und Sie wissen lassen –

+2

Mit 'TestUtils.renderIntoDocument' wird automatisch' componentWillMount ausgelöst 'Funktion. Die erste Option sieht jedoch vielversprechend aus. –

+0

@MichaelParker, ja du hast Recht das ComponentWillMount wird automatisch ausgeführt, aber dann innerhalb des Tests setzen Sie den Zustand manuell und rufen Sie die Methode erneut auf und testen Sie den Zustand erneut 'component.componentWillMount()' usw. – badAdviceGuy

6

Ich bevorzuge den folgenden Ansatz, erfordert aber die Verwendung von ES6-Klassen.

// 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(...) 
    }); 
}); 

Der Punkt ist eine On-Demand Child erben die OriginalClass zu schaffen, was tun außer Kraft setzt und dann TestUtils.renderIntoDocument(<ChildClass />)

Verwandte Themen