Создание теста для асинхронного метода

Поэтому я разрабатывал несколько кодов, используя AWS Lambda с NodeJS 6.10. Из-за отсутствия у меня знаний в области интеграционного тестирования (не волнуйтесь, модульные тесты выполнены) я не тестировал свой код. Конечно, я пропустил ошибку, из-за которой две бессонные ночи. Он продолжает работать даже после того, как я вставил это

return workerCallback(err);

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

SQSService.deleteMessage

называется. Остальные коды не запускались, а лямбда-функция выполнялась и завершалась, как ожидалось.

Вот код, который работает, как ожидалось.

function myFoo(currentRequest,event, workCallback){

    var current_ts = moment();
    var req_ts = moment(currentRequest.request_timestamp);

    if (req_ts.diff(current_ts, 'minutes') > 5) {
    SQSService.deleteMessage(event.ReceiptHandle, function(err, data){
        if (err) {
            return workerCallback(err);
        } else {
            return workerCallback(null, "Request stale! Deleting from queue...");
        }
    }); //end of SQS Service
        return; //This line... this line!
    }

    /* Codes below will execute because the code above is asynchronous
       but it should not as the asynchronous code above is a terminator function 
    from a business logic point of view
    */

    //more codes that will run should currentRequest.request_timestamp is 5 minutes past

 }

Может кто-нибудь посоветовать мне, как протестировать этот код или создать тест, который, по крайней мере, помешал бы мне повторить ту же ошибку снова? Я бы хотел избежать повторения этих ошибок путем тестирования. Спасибо!

помните - вызов SQSService.deleteMessage включает обработчик обратного вызова - и именно в этом обработчике обратного вызова существуют ваши два оператора возврата. Они завершают обработчик обратного вызова всякий раз, когда метод SQSService решает вызвать его. Но они не выполняются в myFoo, поэтому после вызова SQSService.deleteMessage код просто продолжится. Что касается тестирования, я полагаю, вы могли бы поставить утверждение или выдать ошибку после кода, который, по вашему мнению, никогда не должен пройти. Но это не совсем системное решение. Более важный вопрос - зачем вообще нужен код?

Doug 02.05.2018 10:17

ах да ... функция получает сообщения с project_ref_no или без него. Итак, если project_ref_no не определено, удалите сообщение и готово. Полагаю, я мог бы добавить еще для предложения if. Как бы вы это написали?

Francis Zabala 02.05.2018 10:25
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
2
39
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

(Я перехожу к ответу, чтобы поток комментариев не заполнялся - и чтобы я мог печатать больше).

Ключ в том, чтобы получить правильное представление об асинхронности вашего кода. myFoo кажется асинхронным, поэтому вам нужно решить, все ли ошибки или режимы отказа должны обрабатываться как ошибки, передаваемые его обработчику обратного вызова, или некоторые типы ошибок должны возвращать синхронные ошибки вызывающему myFoo самому. Мой общий подход заключается в том, что если какие-либо ошибки проходят через обработчик обратного вызова, все они отправляются туда - с незначительным исключением определенных типов ошибок неправильного кодирования (например, передача вещей неправильного типа или передача null для аргументов в котором всегда должны быть переменные), для которых я мог бы использовать throw Error(). Но если такая ошибка (project_ref_no == null) является той ошибкой, которую вы должны аккуратно обрабатывать, то я, вероятно, передаю ее обработчику ошибок. Общая идея заключается в том, что когда вы вызываете myFoo, и он возвращается, все, что вы знаете, это то, что некоторая работа будет выполнена в какой-то момент, но вы не знаете, что произойдет (и не получите результата. в ответе) - ответ вернется позже при вызове обработчика обратного вызова).

Но, что более важно, важно понимать, какой код запускается немедленно и какой код находится в обработчике обратного вызова. Вы запутались, потому что мысленно представляете, что обработчик внутреннего сгенерированного обратного вызова (переданный в SQSService.deleteMessage) запускался, когда вы вызывали myFoo.

Что касается стратегии тестирования, я не думаю, что есть серебряная пуля в проблеме ошибочного принятия асинхронных вызовов (с обработчиками обратного вызова) с кодом, который выполняется синхронно. Вы можете разбрасывать утверждения или throw Error() повсюду (где, как вы думаете, код никогда не должен попадать), но это сделало бы ваш код смешным.

Typescript немного помогает в этом, потому что вы можете определить тип, возвращаемый функцией, и ваша IDE должна выдавать вам предупреждение, если у вас есть пути кода, которые не возвращают что-то этого типа (что-то больше / все? Типизированные языки дают вам ) - и это немного поможет, но не все случаи (например, функции, возвращающие void).

Если вы новичок в асинхронных моделях javascript и / или javascript, вы можете проверить следующую ссылку:

https://medium.com/codebuddies/getting-to-know-asynchronous-javascript-callbacks-promises-and-async-await-17e0673281ee

Я отвечу, поскольку пытаюсь понять ваш ответ. Надеюсь, это не означает, что я отказался от вопроса. Спасибо!

Francis Zabala 02.05.2018 10:47

Я изменяю код, чтобы сделать его более ориентированным на бизнес-логику. Я просто не знал, что после вызова async коды после этого все равно будут работать. Я думаю, что это фундаментальный способ мышления о том, как кодировать асинхронные функции. Я действительно предполагал, что повторный вызов workerCallback - это то, что закроет функцию. Коды кстати обновил.

Francis Zabala 02.05.2018 11:19

Чтобы было ясно, async - это ключевое слово, которое имеет определенное значение в JavaScript. Метод является асинхронным, если он выполняет асинхронный вызов (например, асинхронный вызов ввода-вывода или какая-либо другая функция, которая принимает обработчик обратного вызова и обещает что-то с ним сделать позже). Ключевое слово async перед определением функции позволяет вам кодировать с помощью асинхронных методов, которые действительно возвращают Promise <XXX>, как если бы это синхронный метод, возвращающий что-то типа XXX. По сути, он «блокирует» вызывающий код до тех пор, пока обещание вызываемого кода не будет выполнено. Вы не используете асинхронный код в своем коде.

Doug 02.05.2018 11:39

Да нет. Это должно прояснить ситуацию. Что касается обещаний, я не удивлен, что об этом здесь упоминается. Я пытался сначала понять, как работают асинхронные функции, прежде чем погрузиться в обещания. Хотя спасибо за вклад

Francis Zabala 02.05.2018 11:57

Асинхронное программирование в старом стиле передается в обработчики обратных вызовов, которые, как ожидается, будут обрабатывать (более поздний) результат. Обещания возвращают дескриптор (отложенного) результата вызывающему, поэтому вызывающий может делать с ним все, что хочет (ждать, собирать несколько и ждать их вместе, передавать их какому-то другому коду и т. д.), И async / await основывается на обещаниях и позволяет вызывающему коду эффективно «блокировать» результат и делать вид, что он синхронный (в то же время позволяя другим «потокам» работать).

Doug 02.05.2018 12:51

Спасибо. Я надеюсь, что некоторые другие разработчики смогут получить представление об этом посте.

Francis Zabala 04.05.2018 04:04

Другие вопросы по теме