Как я могу ожидать, что при тестировании кода NodeJS с утверждениями Mocha и Chai будет выдано исключение из обратного вызова?

Я использую Mocha с утверждениями Chai, ожидающими проверки моего приложения NodeJS. Я могу написать такой тест, и он отлично работает:

describe 'My Code', ->
    it 'should handle exceptions', (done) ->
        fn = ->
            # Do something that causes an error
            throw new Error()
        expect(fn).to.throw(Error)
        done()

Но что, если fn должен сначала вызвать функцию, которая принимает обратный вызов, и может выдать ошибку в зависимости от результата? Например, если он попадает в базу данных и может вызвать исключение на основе результата? Это не работает:

describe 'My Callback-using Code', ->
    it 'should handle exceptions thrown from callbacks', ->

        doSomethingAsync = (callback) ->
            setTimeout (->
                callback(somecalculatedvalue)
            ), 1000


        fn = ->
            doSomethingAsync (value) ->
                # The value meets a condition so throw an error
                throw new Error()

        expect(fn).to.throw(Error)
        done()

Тест заканчивается, когда вызывается done, но исключение еще не выброшено, поэтому тест завершается неудачно. Как я могу пройти этот тест?

РЕДАКТИРОВАТЬ: Согласно ответу Питера, это неправильный подход. Это может быть лучше выражено в стиле, подобном этому:

describe 'My Error Handling Code', ->
    it 'should handle errors', ->

        fn = (callback) ->
            getValueFromDatabase (value) ->
                if value.isBad()
                    callback({ error: 'The value is bad.'})
                else
                    callback()

        fn (e) ->
            expect(e).to.exist()
            done()

Спасибо всем за вашу помощь! Это поможет во многих вещах, над которыми я работаю.


person davidscolgan    schedule 30.01.2014    source источник
comment
Есть несколько способов сделать это, в зависимости от того, где проходит разделительная линия между вашим кодом и чужим кодом. Из вашего вопроса неясно, что вы считаете своим кодом (предположительно, это то, что вы тестируете) и что вы считаете кодом, принадлежащим какой-то библиотеке, которую вы используете.   -  person Louis    schedule 31.01.2014


Ответы (1)


Это ваш собственный код или библиотека, которую вы используете? Генерация исключения после асинхронной операции недопустима в узле. Вы должны передать ошибку в качестве первого аргумента функции обратного вызова. Стек был сброшен, поэтому невозможно перехватить выброшенное исключение. Генерация исключений работает только для синхронного кода, и поэтому вы почти никогда не увидите его в коде узла, потому что асинхронный код постоянно запускает новые стеки без вызова кода, доступного для перехвата исключений.

person Peter Lyons    schedule 30.01.2014
comment
А, это имеет смысл. Контекст этого заключался в том, что я хотел проверить, верно ли условие в базе данных Mongodb, а затем выдать исключение после того, как результат вернется, если возникнет проблема. Но теперь, когда вы это говорите, я заметил, что функция обратного вызова из Mongo возвращает объект ошибки и результат, и я мог бы легко переделать то, что пытался сделать, используя ту же идиому. Большое спасибо за вашу помощь! - person davidscolgan; 31.01.2014