2016-04-20 20 views
1

Ich habe eine App-Komponente, die für das Rendern von untergeordneten Eingabekomponenten zuständig ist. Sie ist auch für die Verarbeitung von Abrufanforderungen an die Twitch-API über eine Methode namens channelSearch zuständig. Ich habe versucht, die empfohlenen Best Practices here zum Arbeiten mit Ajax/Fetch mit React einzuhalten.Testen von fetch() - Methode in React-Komponente

Die Methode wird über Requisiten übergeben und über einen Callback aufgerufen.

Beachten Sie, dass die Fetch-Methode isomorph-fetch ist.

channelSearch (searchReq, baseUrl="https://api.twitch.tv/kraken/channels/") { 
    fetch(baseUrl + searchReq) 
    .then(response => { 
    return response.json(); 
    }) 
    .then(json => { 
    this.setState({newChannel:json}); 
    }) 
    .then(() => { 
    if (!("error" in this.state.newChannel) && this.channelChecker(this.state.newChannel._id, this.state.channelList)) { 
     this.setState(
     {channelList: this.state.channelList.concat([this.state.newChannel])} 
    ); 
    } 
    }) 
    .catch(error => { 
    return error; 
    }); 
} 

Ich versuche zur Zeit einen Test für die channelSearch Methode zu schreiben. Ich verwende derzeit Enzym und Jsdom zu mount die gesamte <App> Komponente in einem DOM. Suchen Sie den untergeordneten Knoten mit dem Rückruf, simulieren Sie einen Klick (der den Rückruf auslösen soll), und prüfen Sie, ob der Status der Komponente geändert wurde. Dies scheint jedoch nicht zu funktionieren.

Ich habe auch versucht, die Methode direkt aufzurufen, jedoch habe ich Probleme mit this.state undefined.

test('channel search method should change newChannel state', t => { 
    const wrapper = mount(React.createElement(App)); 

    wrapper.find('input').get(0).value = "test"; 
    console.log(wrapper.find('input').get(0).value); 
    wrapper.find('input').simulate("change"); 

    wrapper.find('button').simulate("click"); 

    console.log(wrapper.state(["newChannel"])); 


}); 

ich wirklich bin verloren, ich bin nicht sicher, ob die Methode selbst schlecht geschrieben oder ich bin nicht die richtigen Werkzeuge für den Job. Jede Anleitung wird sehr geschätzt.

Update # 1:

I Nock enthalten wie in den Kommentaren zu empfehlen, Test sieht nun wie folgt aus:

test('channel search method should change newChannel state', t => { 
    // Test object setup 

    var twitch = nock('https://api.twitch.tv') 
       .log(console.log) 
       .get('/kraken/channels/test') 
       .reply(200, { 
        _id: '001', 
        name: 'test', 
        game: 'testGame' 
       }); 

    function checker() { 
    if(twitch.isDone()) { 
     console.log("Done!"); 
     console.log(wrapper.state(["newChannel"])); 
    } 
    else { 
     checker(); 
    } 
    } 

    const wrapper = mount(React.createElement(App)); 
    wrapper.find('input').get(0).value = "test"; 
    wrapper.find('input').simulate("change"); 
    wrapper.find('button').simulate("click"); 

    checker(); 
}); 

Diese noch nicht den Zustand der Komponente zu ändern scheint.

+0

Bitte fügen Sie Ihre Tests, wie sie eindeutig Teil der Frage sind :) – markthethomas

+0

@markthethomas Hinzugefügt, vielen Dank für das Interesse! –

Antwort

1

Fetch ist asynchron, aber Sie testen synchron, Sie müssen entweder Fetch mit einem synchronen Schein simulieren oder den Test asynchron durchführen.

nock kann für Sie hier arbeiten.

+0

Ich habe meinen Test aktualisiert, um zu versuchen und zu versuchen, mit Nock zu verspotten, wie vorgeschlagen, jedoch sehe ich immer noch das gleiche Problem. –

0

Ich schlage vor, Sie erstellen ein Beispiel für Ihren Test mit plnkr.

Ich stimme Tom zu, dass Sie synchron testen. . Es wäre natürlich hilfreich sein, Ihre tatsächliche Komponentencode zu zeigen (alle relevanten Bereiche, wie das, was nennt channelSearch, oder zumindest beschreiben, indem sie sagen zB „channelSearch von componentDidMount() genannt“ Du hast gesagt:

ich betreibe Probleme mit this.state undefiniert ist.

Dies liegt daran, this.setState() is asynchronous. Dies aus Gründen der Performance ist, so dass können Batch Veränderungen reagieren.

Ich vermute, Sie müssen Ihren Code ändern, die derzeit:

.then(json => { 
    this.setState({newChannel:json}); 
}) 

zu:

.then(json => { 
    return new Promise(function(resolve, reject) { 
    this.setState({newChannel:json}, resolve); 
    }) 
}) 

Beachten Sie, dass Ihre checker() Methode nicht funktionieren. Es ist Looping, aber twitch.isDone() wird nie wahr sein, weil es nie eine Chance hat zu laufen. Javascript ist single-threaded, so dass Ihr Checker-Code kontinuierlich ausgeführt wird und nichts dazwischen erlaubt.

Wenn Sie die PLNKR einrichten, werde ich einen Blick darauf werfen.