2015-08-11 3 views
1

Я хочу создать единичный тест для асинхронного процесса. Я создал голой макет ситуации, используя тайм-аут для задержки оповещения. (Реальный процесс будет загрузкой JS-файла на лету).Использование Mocha, Chai и Sinon для проверки действия с задержкой

Я только начинаю с Мокки, Чай и Синон. Я создал папку под названием vendor рядом с моим HTML-файлом. Это содержит последние версии 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> 

ответ

1

Ваши утверждения и done() (если тест когда-либо получал там) в настоящее время называется как только тайм-аут установки.

тест устанавливает тайм-аут

this.timeout(5000) 

расписаний тест для запуска в течение 2 секунд, и переходит сразу.

setTimeout(... 

Проверяет утверждение, которое не

sinon.assert.called(spy) 

Затем выходит перед setTimeout есть шанс бежать.

Утверждения должны запускаться после завершения setTimeout и, поскольку мы находимся в браузере, асинхронные утверждения необходимо зафиксировать в блоке try/catch, чтобы фактическое исключение можно было вернуть обратно к мокке через done().

Большинство асинхронного 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, а также упростить чтение.

+0

Спасибо. Если я использую ваш код, но изменяю «Один раз» на «Один» в одном месте, так что утверждение терпит неудачу, я получаю этот вывод: «Ошибка: ошибка скрипта. (: 0) at global.onerror (vendor/mocha.js: 13082: 10) '. Если я прокомментирую вызов 'setTimeout()', тогда я получаю гораздо более полный отчет, включая ожидаемые и фактические выходы, и строку, в которой было сделано неожиданное предупреждение. Есть ли способ достичь этого более полного вывода после асинхронного вызова? –

+0

Итак, я больше использую mocha в node.js, затем ... видимо, в браузере «Ошибка скрипта». (: 0) '- то, как mocha выбрасывает асинхронные исключения, поэтому требуется немного магии try/catch для захвата исключения в' done() ' – Matt