2016-07-08 3 views
1

Я пытаюсь создать тесты мокки для своих контроллеров, используя конфигурацию, которая должна быть загружена async. Ниже мой код. Однако, когда выполняется тест мокки, он не запускает никаких тестов, отображая 0 passing. console.log s никогда не называются. Я попытался сделать before(next => config.build().then(next)) внутри описания, но даже если тесты выполняются, before никогда не вызывается. Есть ли способ загрузить конфигурацию за один раз до запуска любых тестов?Как я могу построить свой тестовый пакет асинхронно?

'use strict'; 

const common = require('./common'); 
const config = require('../config'); 

config 
    .build() 
    .then(test); 


function test() { 
console.log(1); 
    describe('Unit Testing',() => { 
console.log(2); 
     require('./auth'); 
    }); 
} 
+0

Это, как я использую 'before', который не вызывается:' описать ('Unit Testing',() => { ранее (следующая = > config.build(). then (next)); require ('./ auth'); }); ' – terpak

ответ

2

Вы должны запустить Mocha с опцией --delay, а затем использовать run() как только вы закончите строить свой набор тестов. Ниже приведен пример, полученный из кода вы показываете в вопросе:

'use strict'; 

function test() { 
    console.log(1); 
    describe('Unit Testing',() => { 
     console.log(2); 
     it("test",() => { 
      console.log(3); 
     }); 
    }); 

    // You must use --delay for `run()` to be available to you. 
    run(); 
} 

setTimeout(test, 1000); 

Я использую setTimeout для имитации асинхронной операции. Используя --delay и run(), вы можете создать набор, который является результатом асинхронного вычисления. Обратите внимание, однако, что набор должен быть построен одним выстрелом. (Вы не можете иметь асинхронный процесс внутри describe который будет совершать звонки на it Это не будет работать..)


Одна вещь, вы должны определенно не сделать, это то, что rob3c suggests: вызов describe или it (или оба) изнутри крючка. Это ошибка, из-за которой время от времени люди делают так, что стоит подробно остановиться. Проблема в том, что Mocha просто не поддерживается, поэтому нет установленной семантики, связанной с вызовом describe или it изнутри крючка. О, можно писать простые примеры, которые работают, как один не может ожидать, но:

  1. Когда свита становится все более сложной, поведение люкса больше не соответствует ничего толкового.

  2. Поскольку семантики, связанные с этим подходом, не имеют новых версий, новые версии Mocha могут обрабатывать ошибочное использование по-разному и разбивать ваш пакет.

Рассмотрим простой пример:

const assert = require("assert"); 

const p = Promise.resolve(["foo", "bar", "baz"]); 

describe("top",() => { 
    let flag; 
    before(() => { 
     flag = true; 
     return p.then((names) => { 
      describe("embedded",() => { 
       for (const name of names) { 
        it(name,() => { 
         assert(flag); 
        }); 
       } 
      }); 
     }); 
    }); 

    after(() => { 
     flag = false; 
    }); 

    it("regular test",() => { 
     assert(flag); 
    }); 
}); 

Когда мы бежим, мы получим:

top 
    ✓ regular test 

    embedded 
    1) foo 
    2) bar 
    3) baz 

    1 passing (32ms) 
    3 failing 

    // [stack traces omitted for brevity] 

Что здесь происходит? Разве не все тесты проходят? Мы установили flag в true в before крюк для top опишите. Все тесты, которые мы создаем в нем, должны видеть flag как true, нет? Ключ находится в выводе выше: когда мы создаем тесты внутри крючка, Mocha ставит тесты где-то, но может быть не в том месте, которое отражает структуру блоков describe в коде. Что происходит в этом случае - это то, что Mocha просто добавляет тесты, созданные на крючке, самый конец набора, за пределами top, описывается, так что крючок after выполняется перед динамически создаваемыми тестами, и мы получаем контринтуитивный результат ,

Использование --delay и run(), мы можем написать пакет, который ведет себя таким образом, согласные с интуицией:

const assert = require("assert"); 

const p = Promise.resolve(["foo", "bar", "baz"]).then((names) => { 
    describe("top",() => { 
     let flag; 
     before(() => { 
      flag = true; 
     }); 

     after(() => { 
      flag = false; 
     }); 

     describe("embedded",() => { 
      for (const name of names) { 
       it(name,() => { 
        assert(flag); 
       }); 
      } 
     }); 

     it("regular test",() => { 
      assert(flag); 
     }); 
    }); 
    run(); 
}); 

Выход:

top 
    ✓ regular test 
    embedded 
     ✓ foo 
     ✓ bar 
     ✓ baz 


    4 passing (19ms) 
+0

* * * Можно создавать асинхронные динамические тесты для каждого файла. См. Мой ответ ниже для способа, который не использует флаг задержки корневого пакета '--delay' или единственный глобальный' run() 'hook: https://stackoverflow.com/a/48572080/871990 – rob3c

-1

Вы можете просто отделить логику тестирования и загрузки полностью , заверните загрузчик в обещание, которое блокирует тест, пока не будет выполнена конфигурация (очень просто с async/await, если вы используете node8, иначе просто Promise.each результаты).

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

-1

Проблема с помощью флага строки --delay команд и run() обратного вызова, который @Louis упоминается в его принято отвечать, что run() является один глобальный хук что delays the root test suite. Поэтому вы должны собрать их все сразу (как он упомянул), что может сделать организацию тестов суетой (по меньшей мере).

Однако я предпочитаю избегать волшебных флагов, когда это возможно, и я, конечно, не хочу, чтобы управлять всем моим набором тестов в одном глобальном обратном вызове run(). К счастью, есть способ для динамического создания тестов на основе каждого файла, и не требуют каких-либо специальных флагов, либо :-)

Чтобы динамически создавать It() тестов в любой исходный файл теста с использованием данных, полученных асинхронно, вы можете (ab) использовать крючок before() с заполнителем It() тест, чтобы обеспечить мокко до тех пор, пока не будет запущен before(). Вот пример из my answer to a related question, для удобства:

before(function() { 
    console.log('Let the abuse begin...'); 
    return promiseFn(). 
     then(function (testSuite) { 
      describe('here are some dynamic It() tests', function() { 
       testSuite.specs.forEach(function (spec) { 
        it(spec.description, function() { 
         var actualResult = runMyTest(spec); 
         assert.equal(actualResult, spec.expectedResult); 
        }); 
       }); 
      }); 
     }); 
}); 

it('This is a required placeholder to allow before() to work', function() { 
    console.log('Mocha should not require this hack IMHO'); 
}); 
+0

Что вы показываете не поддерживается Моккой. Не существует определенной семантики для вызова 'описать' или' it' из-за крюка 'before'. Для простых примеров (например, здесь) это может выглядеть так, как будто для него определены семантики, но их просто нет. Когда он делает то, что вы ожидаете от этого, это просто * удача *, а не * дизайн *. Я гарантирую вам, что для более сложных наборов вы столкнетесь с ситуациями, когда тесты, которые вы пытаетесь добавить в свой крючок, окажутся в местах тестового дерева, которые кажутся вам странными. – Louis

+0

@Louis Я использовал его уже пару лет без проблем или сюрпризов, поэтому, я думаю, мне просто повезло :-) – rob3c

+0

Да, вам повезло. Поскольку то, что вы делаете, не поддерживается, возможно, появилась новая версия Mocha, которая разбивает ваш код. Если бы вы открыли отчет о проблеме, ответ был бы «Вы пытаетесь сделать что-то, чего не поддерживает Mocha», и проблема была бы закрыта. – Louis