【问题标题】:Using Mocha, Chai and Sinon to test a delayed action使用 Mocha、Chai 和 Sinon 测试延迟动作
【发布时间】:2015-08-11 20:39:04
【问题描述】:

我想为异步进程创建一个单元测试。我已经创建了一个简单的模拟情况,使用超时来延迟警报。 (真正的过程是动态加载 JS 文件)。

我只是从 Mocha、Chai 和 Sinon 开始。我在我的 HTML 文件旁边创建了一个名为 vendor 的文件夹。其中包含最新版本的 mocha.css、mocha.js、chai.js 和 sinon.js。

如果我注释掉 setTimeout() 调用,下面的代码可以正常工作。我应该如何更改它,以便 sinon.assert... 调用将等待延迟操作发生?

<!DOCTYPE html>
<head>
  <title>Delayed alert test</title>
</head>

<body>
<div id="mocha"><p><a href=".">Index</a></p></div>
<div id="messages"></div>
<div id="fixtures"></div>
<link rel="stylesheet" type="text/css" href="vendor/mocha.css" />
<script src="vendor/mocha.js"></script>
<script src="vendor/chai.js"></script>
<script src="vendor/sinon.js"></script>

<script>
mocha.setup('bdd')

var spy = sinon.spy(window, 'alert')

describe("Test", function() {
  describe("#alert", function() {
    it("should show an alert", function(done) {
      this.timeout(5000)

      setTimeout(function () { // Works if these 2 lines...
        alert ("Once")
        alert ("Twice")
      }, 2000)                 // are commented out
      sinon.assert.called(spy)
      sinon.assert.calledTwice(spy)
      sinon.assert.calledWithExactly(spy, "Once")
      sinon.assert.calledWithExactly(spy, "Twice")
      done()
    });
  });
})

mocha.run();
</script>
</body>
</html>

【问题讨论】:

    标签: unit-testing mocha.js chai


    【解决方案1】:

    一旦设置超时,就会立即调用您的断言和 done()(如果测试到达那里)。

    测试设置超时

    this.timeout(5000)
    

    安排您的测试在 2 秒内运行,然后立即继续。

    setTimeout(...
    

    检查失败的断言

    sinon.assert.called(spy)
    

    然后在setTimeout 有机会运行之前退出。

    断言需要在 setTimeout 完成后运行,因为我们在浏览器中,异步断言需要在 try/catch 块中捕获,以便可以通过 done() 将实际异常传递回 mocha。

    大多数异步 API 允许您传入一个“回调”函数,该函数在异步任务完成后调用,这通常是您放入断言/完成的函数。

    在你的情况下,它有点字面意思......

    describe("Test", function() {
      describe("#alert", function() {
        it("should show an alert", function(done) {
          this.timeout(5000)
    
          var stub = sinon.stub(window, 'alert')
    
          var assertion = function(){
            try {
                sinon.assert.called(stub)
                sinon.assert.calledTwice(stub)
                sinon.assert.calledWithExactly(stub, "Oce")
                sinon.assert.calledWithExactly(stub, "Twice")
                done()
            } catch ( e ) {
                done( e )
            }
          }
    
          setTimeout(function () {
            alert ("Once")
            alert ("Twice")
            assertion()
          }, 2000)
    
        });
      });
    })
    

    https://jsfiddle.net/6w4p7rxz/

    注意,我将 spy 更改为 stub 以减少点击次数。也可以使用chai!也许sinon-chai 也可以让事情更容易阅读。

    【讨论】:

    • 谢谢。如果我使用您的代码,但在一个地方将“Once”更改为“One”,因此断言失败,我会得到以下输出:Error: Script error. (:0) at global.onerror (vendor/mocha.js:13082:10)。如果我注释掉setTimeout() 调用,那么我会得到一份更完整的报告,包括预期和实际输出,以及发出意外警报的行。有没有办法在异步调用之后实现这种更完整的输出?
    • 好的,所以我更习惯于 node.js 中的 mocha... 显然在浏览器中 Script error. (:0) 是 mocha 抛出异步异常的方式,因此需要一些 try/catch 魔法在done()中捕获异常
    猜你喜欢
    • 2015-12-01
    • 2018-04-08
    • 1970-01-01
    • 2023-04-11
    • 2020-10-11
    • 2016-01-25
    • 2015-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多