2015-01-08 3 views
0

Я пишу тест, где мне нужно зацикливаться на результатах вызова async api и динамически делать мокко «Его» для проверки каждой итерации ответа. Я нашел некоторые другие связанные ответы, которые заставили меня начать. Вот что я пробовал до сих пор.Bluebird Каждый цикл в Mocha не работает

function getter(uri) { 
    return new Promise(function(resolve, reject) { 
     request({ 
      method: 'GET', 
      json: true, 
      uri: uri 
     }, function(error, response, body) { 
      if (response.statusCode == 200) { 
       resolve(body); 
      } else { 
       reject(error); 
      } 
     }); 
    }); 
} 

describe('This works', function() { 
    it('works', function(done) { 
     getter('myapi_that_returns_an_array').then(function(r) { 
      r.should.not.be.empty; 
      done(); 
     }).catch(function(err) { 
      done(err); 
     }); 
    }); 
}); 


describe('Why not this one', function() { 
    getter('myapi_that_returns_an_array').each(function(r) { 
     it('should make a test', function(done) { 
      r.should.not.be.empty; 
      done(); 
     }); 
    }); 
}); 

Я попытался просто обернуть простой массив в обещание и передать его моему тесту, и он работает! Поэтому я не могу понять, почему вызов api, который я делаю, работает не так.

function simple_test() { 
    return new Promise(function (resolve, reject) { 
     resolve([ [1, 2, 3, 4], [2, 3, 4, 1], [3, 4, 2, 1], [4, 1, 2, 3] ]); 
     }); 
} 

describe('But this one works', function() { 
    two().each(function(r) { 
     it('is a test', function(done) { 
      r.should.not.be.empty(); 
      done(); 
     }); 
    }); 
}); 

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

ответ

2

Версия тест, который пытается генерировать тесты по телефону it внутри getter.each не может работать, потому что Mocha не имеет какие-либо положений для генерирующих испытаний асинхронны что то, что вы пытаетесь сделать. Как я уже объяснил here:

Что вы получаете, связано с тем, как Mocha обнаруживает ваш тест. В основном Mocha делает это:

  1. Прочтите все свои тестовые файлы и выполните их. Обратные вызовы, переданные в describe, выполняются сразу. Обратные вызовы, переданные в it, и на крючки (before, beforeEach и т. Д.), Записываются для последующего исполнения.

  2. Mocha выполняет то, что записал для последующего исполнения (в соответствии с каким-то разумным порядком, который здесь не важен).

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

+1

bummer - возможность генерации тестов асинхронно будет полезна в некоторых ситуациях. Как вы предлагали обойти эту проблему? Наверное, у меня может быть какая-то проверка, которая использует только одно утверждение. – Ptrkcon

0

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

Я не совсем понимаю, почему тест работает асинхронно с небольшим или отсутствующим интервалом таймаута, но мои эксперименты показывают, что it() должен быть вызван по крайней мере один раз, прежде чем describe() вернется, чтобы тесты были распознаны на выходе. С 1 миллисекундным таймаутом я увидел тесты, описанные в родительском блоке.

Использование before() блоков имеет такую ​​же проблему. before() может ждать, пока обещанный массив будет разрешен, но без каких-либо it() тестов статически определены, before() никогда не будет запущен.

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

var assert = require("assert"); 
var Promise = require("bluebird"); 

var testData = [ 
    { "name": "Test 1", "value": true }, 
    { "name": "Test 2", "value": false }, 
    { "name": "Test 3", "value": true } 
]; 

function getTestData(timeout) { 
    return new Promise(function (resolve, reject) { 
     if (timeout) { 
      setTimeout(function() { 
       resolve(testData); 
      }, timeout); 
     } else { 
      resolve(testData); 
     } 
    }); 
} 

describe("Dynamicly Generating Tests", function() { 

    describe("A: Promised Array, no timeout - Works", function() { 
     getTestData().each(function (test) { 
      it("A: " + test.name, function() { 
       assert.ok(test.value); 
      }); 
     }); 
    }); 

    describe("B: Promised Array, short timeout - Works?", function() { 
     getTestData(1).then(function (testData) { 
      testData.forEach(function (test) { 
       it("B:" + test.name, function() { 
        assert.ok(test.value); 
       }); 
      }); 
     }); 
    }); 

    describe("C: Promised Array, timeout, single it() - Works!", function() { 
     it("C: Has all correct values", function() { 
      return getTestData(1000).each(function (test) { 
       assert.ok(test.value, test.name); 
      }); 
     }) 
    }); 

}); 
+0

Серия «B» фактически не работает. Если вы закомментируете 'описание' для« A »и« C », и пусть это будет запущено, вы не получите никаких тестов. Причина в том, что я объясняю в своем ответе. Когда у вас есть «A» и «C» без комментирования, код в «B» по-прежнему удается выполнить, но вы заметите, что сообщение об ошибке не имеет полного тестового имени (ему не хватает текста из 'описания'), потому что Мокка не знает, откуда произошел сбой. – Louis

+0

Согласен, спасибо за то, что он точно разъяснил, почему это так. – James

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