2012-03-16 3 views
42

Этот вопрос относится к среде тестирования Mocha для NodeJS.Как я могу выполнить асинхронные тесты Mocha (NodeJS) в порядке?

поведения

по умолчанию, кажется, чтобы начать все тесты, а затем обработать асинхронные обратные вызовы, как они приходят в.

При выполнении асинхронных тестов, я хотел бы работать каждый тест после Асинхронной части из один из них был вызван.

Как это сделать?

ответ

30

Дело не в том, что «структурированный код работает в том порядке, в котором вы его структурировали» (удивляйтесь!), Но, как предлагает @chrisdew, заказы на возврат для асинхронных тестов не могут быть гарантированы. Чтобы повторить проблему - тесты, которые находятся дальше по цепочке (синхронного исполнения) , не могут гарантировать, что требуемые условия, установленные асинхронными тестами, будут готовы к моменту их запуска.

Поэтому, если вам требуются определенные условия, которые должны быть установлены в первых тестах (например, маркер входа или аналогичный), вы должны использовать крючки, такие как before(), которые проверяют эти условия перед тем, как продолжить.

Wrap зависимые испытания в блоке и запустить асинхроннойbefore крючок на них (обратите внимание на «сделано» в перед блоком):

var someCondition = false 

// ... your Async tests setting conditions go up here... 

describe('is dependent on someCondition', function(){ 

    // Polls `someCondition` every 1s 
    var check = function(done) { 
    if (someCondition) done(); 
    else setTimeout(function(){ check(done) }, 1000); 
    } 

    before(function(done){ 
    check(done); 
    }); 

    it('should get here ONLY once someCondition is true', function(){ 
    // Only gets here once `someCondition` is satisfied 
    }); 

}) 
+0

Как бы «someCondition» когда-либо изменилось, если перед обратным вызовом заблокирован в цикле while ?! Это не то, как работает JavaScript. – natevw

+0

Ответ на ваш вопрос находится в строке комментариев 3: «... ваши условия настройки асинхронных тестов идут здесь». В частности: Async, условия настройки, ограниченные вне 'describe()', которые создаются перед 'before()'. Последнее утверждение о том, что Javascript не работает таким образом, неверно. – papercowboy

+0

Пока ваш код застрял, повторно проверяя! SomeCondition снова и снова, ни один из ваших других кодов не может работать. (Все другие обратные вызовы, связанные с событиями/таймерами, будут предотвращены.) Единственный способ, с помощью которого это могло бы работать, - это когда someCondition устанавливается true до начала цикла, иначе он будет зависать. Попробуй. – natevw

7

Я удивлен тем, что вы написали, когда я использую. Я использую mocha с тестами стиля bdd (описать/это) и просто добавил некоторые тесты console.logs в свои тесты, чтобы проверить, соответствуют ли ваши претензии моим случаем, но, похоже, они этого не делают.

Вот фрагмент кода, который я использовал для просмотра порядка «end1» и «start1». Они были надлежащим образом заказаны.

describe('Characters start a work', function(){ 
    before(function(){ 
     sinon.stub(statusapp, 'create_message'); 
    }); 
    after(function(){ 
     statusapp.create_message.restore(); 
    }); 
    it('creates the events and sends out a message', function(done){ 
     draftwork.start_job(function(err, work){ 
     statusapp.create_message.callCount.should.equal(1); 
     draftwork.get('events').length.should.equal(
      statusapp.module('jobs').Jobs.get(draftwork.get('job_id')).get('nbr_events') 
     ); 
     console.log('end1'); 
     done(); 
     }); 
    }); 
    it('triggers work:start event', function(done){ 
     console.log('start2'); 
     statusapp.app.bind('work:start', function(work){ 
     work.id.should.equal(draftwork.id); 
     statusapp.app.off('work:start'); 
     done(); 
     }); 

Конечно, это могло произойти случайно тоже, но у меня есть много тестов, и если они будут работать параллельно, я бы, безусловно, есть условия гонки, что у меня нет.

Обратите внимание также на this issue с отслеживания проблем мокко. В соответствии с этим тесты выполняются синхронно.

+0

Это только показывает, что упорядоченный код запускается по порядку. Это происходит не случайно. Это «как это работает». – papercowboy

+0

Это показывает, что упорядоченные асинхронные тесты выполняются в порядке: 'end1' всегда будет иметь место до' start2'. Чтобы упростить пример, вы можете заменить содержимое первого теста на 'setTimeout (done, 1000)'.И если вы замените крюк 'before' на асинхронный, он всегда будет работать до первого теста. Насколько я понимаю, это именно то поведение, которое интересовало начало темы, и это поведение по умолчанию и единственное, по крайней мере, к настоящему времени. – skozin

5

Я хотел решить этот же вопрос с нашим приложением , но accepted answer не подходит для нас. Особенно в someCondition никогда не будет правдой.

Мы используем обещания в нашем приложении, и это упростило структуру тестов. Ключ, однако, по-прежнему отложить исполнение через before крючок:

var assert = require("assert"); 

describe("Application", function() { 
    var application = require(__dirname + "/../app.js"); 
    var bootPromise = application.boot(); 

    describe("#boot()", function() { 
    it("should start without errors", function() { 
     return bootPromise; 
    }); 
    }); 

    describe("#shutdown()", function() { 
    before(function() { 
     return bootPromise; 
    }); 

    it("should be able to shut down cleanly", function() { 
     return application.shutdown(); 
    }); 
    }); 
}); 
+3

Лучше разместить вторую и третью строки кода ('application = ...' и 'bootPromise = ...') внутри блока async 'before' в пакете верхнего уровня (« Приложение »). В противном случае любое исключение, исключенное из этого кода, не будет обнаружено и сообщено должным образом и, что еще хуже, предотвратит выполнение всех оставшихся тестов. – skozin

4

использование mocha-steps

он держит тесты последовательным независимо, если они асинхронные или нет (то есть ваши done функции по-прежнему работает точно так же, как они это делали). Это прямая замена для it, и вместо этого вы используете step

+0

Почему это проголосовали? –

+1

@JackMurphy хороший вопрос. – WiR3D

+0

То же самое. У меня была та же проблема, и это помогло мне. – hrishioa

Смежные вопросы