在具有异步功能的存根中不调用sinon spy

nor*_*tpy 4 javascript unit-testing promise sinon enzyme

使用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>);
  }
}
Run Code Online (Sandbox Code Playgroud)

如果我只是检查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();
});
Run Code Online (Sandbox Code Playgroud)

ale*_*mac 12

Api.get是异步函数,它返回一个promise,所以要在test中模拟异步调用,你需要调用resolves函数而不是returns:

使存根返回一个Promise,它解析为提供的值.在构造Promise时,sinon使用Promise.resolve方法.您有责任在不提供Promise的环境中提供polyfill.

sinon
  .stub(Api, 'get')
  .resolves('ok');
Run Code Online (Sandbox Code Playgroud)