2015-11-17 2 views
1

У меня есть приложение MEAN, и я пытаюсь получить тесты для работы на стороне узла. Асинхронные события завершаются обещаниями, которые потребляются в контроллере. Я потерпел неудачу в тестировании контроллер :(Тестирование функции, которая потребляет обещания

Контроллер Я пытаюсь тест:

ProjectController.prototype.getAll = function(req, res, next) { 
    req.dic.subjectRepository 
    .getById(req.params.subjectId) 
    .then(function(subject) { 
    res.json(subject.projects); 
    }, function(err) { 
    return res.status(404).send('Subject does not exist.' + err); 
    }); 
}; 

subjectRepository наш источник данных, который возвращает обещание (mpromise, потому что под капотом мы используем mongoose, но это не имеет значения):

Таким образом, в нашем тесте мы попытались насмешливым запрос (мы инъекционный нашей зависимость инъекционного контейнер из промежуточного слоя в req) и ответ (тест завершается успешно, если response.json() был назван с предметы, которые мы пытались извлечь) и наш предметRepository. Мы использовали bluebird (хотя я пытался другие из разочарования), чтобы создать фальшивые обещания для наших издевались subjectRepository:

describe('SubjectController', function() { 

    'use strict'; 

    var Promise = require('bluebird'); 

    it('gets all existing subjects', function() { 

    // ------------------------------------- 
    // subjectRepository Mock 
    var subjectRepository = { 
     getAll: function() {}, 
    }; 
    var subjectPromise = Promise.resolve([ 
     {name: 'test'}, 
     {name: 'test2'}, 
    ]); 
    spyOn(subjectRepository, 'getAll').andReturn(subjectPromise); 

    // ------------------------------------- 
    // request mock 
    var req = { 
     dic: { 
     subjectRepository: subjectRepository, 
     }, 
    }; 

    // ------------------------------------- 
    // response mock 
    var res = { 
     json: function() {}, 
     send: function() {}, 
    }; 
    spyOn(res, 'json'); 

    // ------------------------------------- 
    // actual test 
    var subjectController = new (require('../../../private/controllers/SubjectController'))(); 
    subjectController.getAll(req, res); 

    // this succeeds 
    expect(subjectRepository.getAll).toHaveBeenCalled(); 

    // this fails 
    // expect(res.json).toHaveBeenCalled(); 
    }); 
}); 

Вопрос: Как мне сделать пробный запуск expect() ПОСЛЕ обещанию удалось?

Узел v0.12

код на GitHub для тех, кто заинтересован: https://github.com/mihaeu/fair-projects

А может быть, я должен отметить, что контроллер называется от маршрутизатора:

// router handles only routing 
// and controller handles data between view and model (=MVC) 
subjectRouter.get('/:subjectId', subjectController.get); 

I заставил это работать, изменив наши контроллеры, чтобы передать обещания, но я не уверен, что это то, что мы хотим. Разве нет способа заставить мой подход к работе?

it('gets all existing subjects', function(done) {  

     // ... 

    var subjectController = new (require('../../../private/controllers/SubjectController'))(); 
    subjectController.getAll(req, res).then(function() { 
     expect(res.json).toHaveBeenCalledWith(testSubjects); // success 
    }).finally(done); 
    expect(subjectRepository.getAll).toHaveBeenCalled(); // success 
    } 
+0

Очень сложно, так как ваш метод getAll не возвращает обещание. Если это так (как в вашем обновлении), это должно быть легко. – Bergi

ответ

1

Ваш код ошибочно смешивает бизнес-логику с маршрутизацией на передней панели.

Если GETALL сделал не сенсорный запрос и объект ответа, это будет выглядеть примерно так:

ProjectController.prototype.getAll = function(subjectId) { 
    return req.dic.subjectRepository.getById(subjectId).then(function(subject){ 
    return subject.projects; 
    }); 
}; 

Теперь он больше не связан с запроса жизненного ответа цикла или заряда логики , тестирование его тривиален по:

it("does foo", function(){ 
    // resolve to pass the test, reject otherwise, mocha or jasmine-as-promised 
    return controller.getAll(152).then(...) 
}); 

это сделает ваш фактического обработчик выглядит следующим образом:

app.get("/projects", function(req, res){ 
    controller.getAll(req.params.subjectId).then(function(result){ 
     res.json(result); 
    }, function(){ 
     res.status(404).send("..."); 
    }); 
}); 
+0

Спасибо за быстрый ответ Бенджамин. Таким образом, вы сделали Контроллер моделью, и он просто передает то же самое обещание. Мой следующий вопрос: как проверить обратный вызов в маршруте. В MVC задача контроллера заключается в том, чтобы действовать как «контроллер» между представлением и моделью. // наш маршрутизатор вводит репозиторий в контроллер, а контроллер // является извлеченным обратным вызовом, который вы отправили (обратные вызовы сложнее проверить // и маршрутизация будет смешана с логикой управления) subjectRouter.get ('/ ', subjectController.getAll); –

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