我有一个负责渲染子输入组件的App组件,它还负责通过一个名为channelSearch
的方法处理对Twitch API的提取请求。我尝试遵循建议的here概述的最佳做法,以便使用React进行ajax / fetch。
该方法通过道具传递,并通过回调调用。
请注意,fetch方法实际上是isomorphic-fetch。
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;
});
}
我目前正在尝试为channelSearch
方法编写测试。我目前正在使用酶和jsdom来mount
DOM中的整个<App>
组件。使用回调查找子节点,模拟单击(应该触发回调)并检查组件的状态是否已更改。但是,这似乎不起作用。
我也试过直接调用该方法,但是,我遇到了this.state
未定义的问题。
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"]));
});
我真的迷路了,我不确定这个方法本身写得不好,或者我没有使用正确的工具来完成工作。任何指导将不胜感激。
更新#1:
我在评论中建议包括nock,现在测试看起来像这样:
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();
});
这似乎仍未改变组件的状态。
答案 0 :(得分:1)
fetch是异步的,但是你要进行同步测试,你需要使用同步模拟进行模拟获取或者使测试异步。
nock可能适合您。
答案 1 :(得分:0)
我建议您使用plnkr创建测试样本。
我同意汤姆你正在同步测试。展示您的实际组件代码(所有相关部分,例如调用channelSearch
,或者至少通过说“channelSearch
调用{{1}来描述它当然会很有帮助你说:
我遇到了这个问题。状态未定义。
这是因为this.setState()
is asynchronous。这是出于性能原因,因此React可以批量更改。
我怀疑您需要更改当前的代码:
componentDidMount()
以强>
.then(json => {
this.setState({newChannel:json});
})
请注意,您的.then(json => {
return new Promise(function(resolve, reject) {
this.setState({newChannel:json}, resolve);
})
})
方法无效。它正在循环,但checker()
将永远不会成为现实,因为它永远不会有机会运行。 Javascript是单线程的,因此您的检查器代码将连续运行,不允许其他任何内容。
如果你设置了plnkr,我会看看。
答案 2 :(得分:0)
从组件中重构fetch
代码,然后将其作为回调函数传递到组件中。
export class Channel extends React.Component {
componentDidMount() {
this.props.searchFunction().then(data => this.setState(data));
}
render() {
return <div>{this.state}</div>;
}
}
用法:
function channelSearch(name) {
return fetch(`https://api.twitch.tv/kraken/search/channels?query=${name}`);
}
<Channel searchFunction={channelSearch} />
现在,您可以独立于组件测试API功能。