2017-09-14 70 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