2016-12-20 4 views
4

Я проверяю эту функцию:Ошибка необработанного отказа. Даже если тесты проходят

UserController.prototype.getDashboard = function getDashboard(req, res, next) { 
    let pages, user; 

    return this.User.findById(req.user.id) 
    .populate('club') 
    .execAsync() 
    .then(dbUser => { 
     user = dbUser; 
     FB.setAccessToken(user.token); 

     return FB.getAsync('me/accounts') 
    }) 
    .then(fbPages => { 
     pages = fbPages.data; 

     return Promise.all(pages.map(page => { 
     return FB.getAsync(`${page.id}/events`) 
      .then(events => events) 
      .catch(e => next(Boom.wrap(e))); 
     })) 
    }) 
    .then(events => { 
     let entity = { 
     user, 
     pages: _.map(pages, (page, i) => _.assign({}, page, { events: events[i].data })) 
     }; 

     return res.send(entity); 
    }) 
    .catch(err => next(Boom.wrap(err))); 
}; 

Но когда я проверить это, даже если она проходит, я получаю Unhandled rejection Error

Это мой тест:

it('handles errors', (done) => { 
    let mockError = new Error('test-error'); 
    let mockRequest = { user: { id: mockUser._id }}; 
    let mockNext = td.function(); 
    let capture = td.matchers.captor(); 

    td.replace(FB, 'getAsync'); 
    td.when(FB.getAsync('me/accounts')) 
    .thenReturn(Promise.resolve(usersTestData.getDashboard.pages)); 

    td.when(FB.getAsync(`1769754093273789/events`)) 
    .thenReturn(Promise.resolve(usersTestData.getDashboard.events[0])) 

    // Promise rejection was handled asynchronously 
    td.when(FB.getAsync(`731033223716085/events`)) 
    .thenReturn(Promise.reject(mockError)) 

    td.when(mockNext(Boom.wrap(mockError))) 
    .thenDo(() => { done() }); 

    controller.getDashboard(mockRequest, _.noop, mockNext); 
}); 

Странная часть - это то, что она проходит. Поэтому mockNext вызывается с ожидаемым, но я получаю журнал в консоли с необработанным отказом. Я попытался обработать .catch для каждого значения отображения, но он по-прежнему показывает ту же ошибку (предупреждение?).

Я использую обещания Bluebird, mongoose (promisified) и testdouble. BTW это журнал с консоли после запуска теста:

dashBoard 
Unhandled rejection Error: test-error 
✓ handles errors 
+0

Вы уверены, что вы хотите назвать 'next' несколько раз? – Bergi

+0

Кстати, взгляните на [Как мне получить доступ к предыдущим обещаниям в цепочке '.then()?] (Http://stackoverflow.com/q/28250680/1048572) о том, как избежать этих« страниц »и переменные 'user' – Bergi

+0

Первоначально у него там не было. Карта была просто 'Promise.all (pages.map (page => FB.getAsync (' $ {page.id}/events'))) ' –

ответ

2

После многих проб и ошибок я обнаружил, что происходит. Проблема связана с testdouble API .thenReturn().

Ошибка появилась, если .thenReturn(Promise.reject(...)) Я настроил td, чтобы использовать обещания Bluebird и использовал их API для обещаний .thenReject(...). Итоговый тестовый код:

td.config({ promiseConstructor: require('bluebird') }); 

it('handles errors', (done) => { 
    let mockError = new Error('test-error'); 
    let mockRequest = { user: { id: mockUser._id }}; 
    let mockNext = td.function(); 
    let capture = td.matchers.captor(); 

    td.replace(FB, 'getAsync'); 
    td.when(FB.getAsync('me/accounts')) 
    .thenReturn(Promise.resolve(usersTestData.getDashboard.pages)); 

    td.when(FB.getAsync(`1769754093273789/events`)) 
    .thenResolve(usersTestData.getDashboard.events[0]) 

    td.when(FB.getAsync(`731033223716085/events`)) 
    .thenReject(mockError) 

    td.when(mockNext(Boom.wrap(mockError))) 
    .thenDo(() => { done() }); 

    controller.getDashboard(mockRequest, _.noop, mockNext); 
}); 

Этот тест будет работать без предупреждений.

1

Я думаю, что проблема с

td.when(FB.getAsync(`731033223716085/events`)) 
.thenReturn(Promise.reject(mockError)) 

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

function ignore(e) {} 
function ignoredRejection(e) { 
    var p = Promise.reject(e); 
    p.catch(ignore); 
    return p; 
} 

td.when(FB.getAsync(`731033223716085/events`)) 
.thenReturn(ignoredRejection(mockError)) 

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

  • Нет связанных вопросов^_^