2016-05-27 5 views
3

У меня есть некоторые JavaScript-код:Как я могу тестировать сложную цепочку обещаний?

var findLeastUsedPassage; 

findLeastUsedPassage = function(StudentId) { 
    var passageCounts; 
    passageCounts = []; 
    return db.Passage.findAll({ 
    where: { 
     active: true 
    } 
    }).each(function(dbPassage) { 
    var passage; 
    passage = dbPassage.get(); 
    passage.count = 0; 
    return passageCounts.push(passage); 
    }).then(function() { 
    return db.Workbook.findAll({ 
     where: { 
     SubjectId: 1, 
     gradedAt: { 
      $ne: null 
     }, 
     StudentId: StudentId 
     }, 
     include: [ 
     { 
      model: db.WorkbookQuestion, 
      include: [db.Question] 
     } 
     ], 
     limit: 10, 
     order: [['gradedAt', 'DESC']] 
    }); 
    }).each(function(dbWorkbook) { 
    return Promise.resolve(dbWorkbook.WorkbookQuestions).each(function(dbWorkbookQuestion) { 
     var passageIndex; 
     passageIndex = _.findIndex(passageCounts, function(passageCount) { 
     return passageCount.id === dbWorkbookQuestion.Question.PassageId; 
     }); 
     if (passageIndex !== -1) { 
     return passageCounts[passageIndex].count++; 
     } 
    }); 
    }).then(function() { 
    passageCounts = _.sortBy(passageCounts, 'count'); 
    return passageCounts; 
    }); 
}; 

и я хочу модульного тестирования (я думаю). Я инструментальный mocha сделать тестирование, но мой тест не кажется, что .. тщательный:

describe('Finding the least used Passage', function() { 
    it('should have a function called findLeastUsedPassage', function() { 
    return expect(WorkbookLib.findLeastUsedPassage).to.exist; 
    }); 
    return it('should return the least used passages for a student', function() { 
    return WorkbookLib.findLeastUsedPassage(10).then(function(passageCounts) { 
     var passageCountsLength; 
     passageCountsLength = passageCounts.length; 
     expect(passageCountsLength).to.equal(74); 
     expect(passageCounts[0].count).to.be.at.most(passageCounts[1].count); 
     expect(passageCounts[1].count).to.be.at.most(passageCounts[5].count); 
     expect(passageCounts[56].count).to.be.at.most(passageCounts[70].count); 
     return expect(passageCounts[70].count).to.be.at.most(passageCounts[73].count); 
    }); 
    }); 
}); 

Что такое правильный подход к модульному тестированию что-то вроде этого?

ответ

3

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

В настоящее время вы не можете проверить код, потому что логика все перемежается между несколькими вызовами базы данных, бизнес-логикой и кодом клея. Что вам нужно сделать, так это разбить все на несколько именованных функций, которые каждый do one thing, как и сейчас. Ожидайте, что вместо создания функций в цепочке вы должны создать их за пределами цепочки, а затем просто вызвать их в цепочке обещаний.

var passageCounts = []; 


function findAllActivePassages() { 
    passageCounts = []; 

    return db.Passage.findAll({ 
    where: { 
     active: true 
    } 
    }) 
} 

function countPassages(dbPassage) { 
    var passage; 
    passage = dbPassage.get(); 
    passage.count = 0; 
    return passageCounts.push(passage); 
} 

function findAllSubjects(StudentId) { 
    return db.Workbook.findAll({ 
    where: { 
     SubjectId: 1, 
     gradedAt: { 
     $ne: null 
     }, 
     StudentId: StudentId 
    }, 
    include: [ 
     { 
     model: db.WorkbookQuestion, 
     include: [db.Question] 
     } 
    ], 
    limit: 10, 
    order: [['gradedAt', 'DESC']] 
    }); 
}) 

// ... 

findAllActivePassages() 
    .each(countPassages) 
    .then(function() { 
    return findAllSubjects(studentId) 
    }) 
    // ... 

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

+0

Как бы я тогда эффективно проверить findAllActivePassages? – Shamoon

+0

Поскольку findAllActivePassages - это просто вызов базы данных, вам, вероятно, не нужен единичный тест, если вы доверяете правильному возврату 'db.Passage.findAll' (сторонний код, который вам не нужен для модульного теста, только ваш только код) –

+0

Итак, в моем коде, что бы я хотел проверить? – Shamoon

1

Итак, для начала вы, вероятно, захотите разбить цепочки обещаний, чтобы сделать отдельные единицы вашего кода более очевидными. Я сделал несколько быстрых psuedo javascript (большинство familiar w/node так извиняюсь, если это не соответствует javascript vanilla как чисто).

var p1 = db.Passage.findAll({ where: { active: true }}) 
var p2 = db.Workbook.findAll({ 
     where: { 
     SubjectId: 1, 
     gradedAt: { 
      $ne: null 
     }, 
     StudentId: StudentId 
     }, 
     include: [ 
     { 
      model: db.WorkbookQuestion, 
      include: [db.Question] 
     } 
     ], 
     limit: 10, 
     order: [['gradedAt', 'DESC']] 
    }); 

Promise.all([p1, p2]) 
.then(function(results){ 
    var passages = results[0] 
    var workbooks = results[1]; 

    var passageCounts = {}; 
    passages.foreach(function(passage){ 
     passagecounts[passage.get().id] = 0 
    }); 

    workbooks.foreach(function(workbook){ 
     workbook.workBookQuestions.foreach(function(question){ 
      return passageCounts[dbWorkbookQuestion.Question.PassageId] += 1; 
     }) 
    }); 

    return Promise.resolve(passageCounts) 
}).then(function(passageCounts){ 
    passageCounts = _.sortBy(passageCounts, 'count'); //this has to change but don't know what underscore offers for sorting an object used as a hashmap 
    return passageCounts; 
}); 

Теперь, что касается модульного тестирования - вы хотите, чтобы проверить дискретные единицы его так, следующие случаи использования кажутся разумными:

  • Могу ли я получить какой-либо результат назад, когда ожидается?
  • Если я даю ему конкретные значения, они сортируются так, как я ожидаю?
  • Если у меня нет результатов для запроса, это сломается? Должно ли это?

Возможно, вам удастся вырвать вызовы БД из логики и передать результаты в метод, что упрощает тестирование некоторых сценариев.

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