【问题标题】:sinon spy is not called in a stub with async functionsinon spy 不会在具有异步函数的存根中调用
【发布时间】:2018-02-23 21:55:24
【问题描述】:

使用sinon 和enzyme 我想测试以下组件:

// 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();
});

【问题讨论】:

    标签: javascript unit-testing promise sinon enzyme


    【解决方案1】:

    我遇到了与间谍类似的问题,使用await Promise.all(spy.returnValues)对我来说效果很好。这解决了所有的承诺,然后我可以检查spy.called。

    【讨论】:

      【解决方案2】:

      你的 console.log(data) 总是发生,因为你的 Promise 确实解决了,它只是在测试完成后才这样做,这就是断言失败的原因。

      通过将它包装在 setTimeout 中,您可以在循环中创建另一个事件,这允许您的 Promise 在测试完成之前解析,这意味着您的断言现在将通过。

      在对异步代码进行单元测试时,这是一个相当常见的问题。通常通过将断言包装在setImmediate 中并从setImmediate 的回调中调用done 来解决。

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

      【讨论】:

        【解决方案3】:

        Api.get 是异步函数,它返回一个承诺,因此要在测试中模拟异步调用,您需要调用 resolves 函数而不是 returns:

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

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

        【讨论】:

        • 原谅我的无知,我修复了错误,但得到了相同的结果。
        • @norbertpy 我已经更新了演示,它在那里工作。我明白为什么它在你的工作中不起作用,这是因为你正在测试异步函数(即使被存根,它仍然是异步的),但不要等待它何时完成,并检查 spy.called。您必须在那里添加then 回调和断言spy.called。 The fixed demo
        • 谢谢。问题是 componentDidMount 没有返回承诺。所以我不能then它。做断言。不过谢谢你的回答。
        猜你喜欢
        • 2019-07-17
        • 1970-01-01
        • 2017-04-21
        • 2018-01-25
        • 2017-02-12
        • 1970-01-01
        • 2018-07-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多