2017-09-14 45 views
1

使用sinonenzyme叫我想測試以下組件:興農間諜不是在存根與異步功能

// Apple.js 
class Apple extends Component { 

    componentDidMount =() => { 

    this.props.start(); 
    Api.get() 
     .then(data => { 
     console.log(data); // THIS IS ALWAYS CALLED 
     this.props.end(); 
     }); 
    } 

    render() { 
    return (<div></div>); 
    } 
} 

如果我只是檢查endApy.called,它總是假的。但是將其包裝在setTimeout中將使其通過。爲什麼console.log()總是被調用,但不是props.end?爲什麼setTimeout修復它?有沒有更好的方法來做到這一點?

// Apple.test.js 
import sinon from 'sinon'; 
import { mount } from 'enzyme'; 
import Api from './Api'; 
import Apple from './Apple'; 


test('should call "end" if Api.get is successfull', t => { 
    t.plan(2); 
    sinon 
     .stub(Api, 'get') 
     .returns(Promise.resolve()); 

    const startSpy = sinon.spy(); 
    const endApy = sinon.spy(); 

    mount(<Apple start={ startSpy } end={ endApy } />); 

    t.equal(startSpy.called, true);     // ALWAYS PASSES 
    t.equal(endSpy.called, true);      // ALWAYS FAILS 
    setTimeout(() => t.equal(endApy.called, true)); // ALWAYS PASSES 

    Api.get.restore(); 
}); 

回答

2

Api.get是異步函數,它返回一個承諾,所以要模仿異步調用的測試,你需要調用resolves功能不returns

導致存根返回一個承諾,其解析爲提供的價值。構建Promise時,sinon使用Promise.resolve方法。您有責任在不提供Promise的環境中提供polyfill。

sinon 
    .stub(Api, 'get') 
    .resolves('ok'); 
+0

請原諒我的無知,我固定的錯誤,但我得到了相同的結果。 – norbertpy

+0

https://repl.it/LHde/2 – norbertpy

+0

@norbertpy我已經更新了演示,它在那裏工作。我明白爲什麼它在你的系統中不起作用,這是因爲你正在測試異步函數(即使在存根時,它仍然是異步),但不要等待它完成,並檢查'spy.called'。你必須在那裏添加'then'回調並聲明'spy.called'。 [The fixed demo](https://repl.it/LHde/4) – alexmac

2

console.log(data)總是會發生的,因爲你的承諾沒有解決,只是這樣做試驗後已經完成,這就是爲什麼斷言失敗。

通過將它包裝在setTimeout中,您可以在循環中創建另一個事件,它允許您的Promise在測試結束前解析,這意味着您的斷言現在會通過。

單元測試異步代碼時,這是一個相當普遍的問題。通常在setImmediate中包裝斷言並從setImmediate的回調中呼叫done解決。

https://stackoverflow.com/a/43855794/6024903