2016-11-11 5 views
0

Könnte mir jemand beim Testen async/Promise-basierter Methoden in React-Komponenten helfen? Zum Beispiel habe ich folgende wirklich einfach Reagieren Komponente (es ist nur Dummy-Code)Wie testet man Async-Methoden in React?

import server from './server'; 

class Button extends Component { 
    async handleClick() { 
    if (await canDoSomething()) { 
     const result = await calculateIt(); 
     if (result) { 
     // will be mocked in my unit test 
     await server.sendResultToServer(result); 
     localStorage.setItem('sent', 'true'); 
     } 
     localStorage.setItem('sent', 'false'); 
    } 
    if (localStorage.getItem('sent') === 'true') { 
     // do something 
    } 
    } 

    render() { 
    return <button onClick={this.handleClick}>Click me</button>; 
    } 
} 

Jetzt in meinem Test habe ich die meisten der Asynchron-Methoden mit sinon wie so spotten konnte:

it('should do something', async() => { 
    const promise = Promise.resolve(); 
    sinon.stub(server, 'sendResultToServer',() => promise); 
    const wrapper = shallow(<Button />); 
    wrapper.find(<button />).simulate('click'); 
    // this await will be resolved FIRST. Only then 
    // await server.sendResultToServer(result); in my code will be resolved 
    await promise; 
    expect(localStorage.getItem('sent')).to.equal('true'); 
}) 

Wenn Sie zum ersten Mal sehen Bei diesem Code sollte man denken, dass alles in Ordnung ist. Aber leider ist es nicht. In meinem Test erwarte ich das Versprechen await promise; und nach, dass ich meine Erwartungen erfülle. Aber auch der Implementierungscode wartet auf das Versprechen. Also wenn das Versprechen in beide Plätze erfüllt die Erwartungen vor läuft der Code in der Implementierung läuft. Mit anderen Worten: mein Test läuft vor dem zu testenden Code (getestet auf meinem Rechner mit Mocha/Chai/Enzyme). Was ich brauche, ist die umgekehrte Reihenfolge.

Kann jemand das lösen?

+0

Sie nie –

+0

die Click-Handler in Ihrem Test rufen Und wie testen Sie die Funktion handle()? In meinem Beispiel ist es innerhalb der Reaktionskomponente. Aber ich könnte es über die React-Komponente schreiben und nicht exportieren. Der einzige, der auf die Funktion zugreifen kann, ist der Click-Handler. – LongFlick

Antwort

0

Sie benötigen Click-Handler auszulösen:

it('should do something', async() => { 
    const promise = Promise.resolve(); 
    sinon.stub(server, 'sendResultToServer',() => promise); 
    const wrapper = shallow(<Select />); 
    wrapper.simulate('click') 
    await promise; 
    expect(localStorage.getItem('sent')).to.equal('true'); 
}) 
+0

Ah Entschuldigung, mein Schlechter. Das passiert beim Kopieren und Einfügen. Ich habe das schon gemacht und das ist genau mein Problem: * nach * dem Event ist die Zusage nicht garantiert. Das Versprechen im Test wird früher als das Versprechen in meinem Code gelöst. Ich werde meine Frage aktualisieren/beheben. – LongFlick

+0

Was ist mit 'canDoSomething' wo kommt es her, scheint so zu sein, als müsste dies verspottet werden –

+0

Das ist eine gute Frage. Es gibt keinen "Exit" in meinem Code an diesem Punkt. Stellen Sie sich vor, dass ich an dieser Stelle auf eine neue Route umlenke. Oder ich mache hier nichts. Ich zeige nur einen Fehler an, wenn einer auftritt. Wenn kein Fehler auftritt (gesendet = wahr), tue ich nichts. Vielleicht habe ich hier ein architektonisches Problem, je mehr ich darüber nachdenke. – LongFlick