#angular #unit-testing #karma-jasmine #angular7 #angular-test
#angular #модульное тестирование #карма-jasmine #angular7 #angular-тест
Вопрос:
Есть ли способ избежать двойного async( async(){} )
синтаксиса в модульном тестировании Angular 7 при объединении поддержки async с async..await
ключевыми словами?
Я новичок в angular, но являюсь опытным программистом, и у меня возникли проблемы с выбором моего предпочтительного стиля тестирования.
Я хотел бы безопасно использовать async..await
в тестах, и я понимаю приведенный ниже синтаксис. Однако при обучении разработчиков, не знакомых с современным javascript и / или концепцией async..await
двойного async(async())
синтаксиса, это кажется им избыточным и сбивающим с толку. Они не учитывают внешнюю асинхронность. Исключения, возникающие в службе, приводят к тому, что сообщения о сбоях появляются вне фактического теста, что трудно отследить.
Кажется, что одно из следующих было бы лучше:
it()
должно волшебным образом поддерживатьasync..await
и обернуть мой обратный вызов вasync()
, чтобы мне не приходилось думать об этом.it()
должен принимать необязательный параметр функции (т. Е.async
илиfakeAsync
), который завершит мой обратный вызов.it()
должны существовать вариантыita()
иitfa()
, которые завершат мой обратный вызов соответствующим помощником async.it()
завершает мой обратный вызов с помощьюasync
, а дополнительныйitf()
завершит мой обратный вызов с помощьюfakeAsync
.
Мне не хватает существующей концепции или синтаксиса? Есть ли лучшая альтернатива?
import { async } from '@angular/core/testing';
describe('MyService', () => {
let service: MyService;
...
it('should get data', async( async() => {
// arrange
let expectedData = { answer: 42 };
// act
let data = await service.getDataAsync();
// assert
expect(data).toEqual(expectedData);
} ));
})
Комментарии:
1. Что касается «запутанности», может быть, теперь, когда они переименованы
async()
какwaitForAsync()
, это немного проще понять?
Ответ №1:
существует несколько различных способов обработки асинхронного тестирования:
- Используйте встроенную функцию karma doneFunction:
(doneFunction) => {async test here... then eventually call done();}
. Это дает вам точный контроль над тем, где заканчивается ваш тест, но заставляет вас как бы самостоятельно обрабатывать ошибки с помощьюdone.fail(error)
. - Завершите с помощью функции angular async(). Это часть вашего примера выше, но, как вы заметили, похоже, что функция Angular async автоматически не поддерживает синтаксис await внутри, что требует использования внутренней async для получения поддержки await.
- Используйте функцию-оболочку Angular fakeAsync(), которая позволяет вам вызывать
tick()
в любом месте вашего кода для имитации течения времени и разрешения наблюдаемых значений, обещаний и других асинхронных функций. Один недостаток: вы не можете выполнять HTTP-вызовы в этом, поскольку они будут выполняться в режиме реального времени.
Хотя я обнаружил, что у каждого из 3 методов есть свои плюсы и минусы, я обнаружил, что # 2 является наиболее полезным для создания плавного прохождения теста, который легко читается. Итак, хотя вы могли бы избежать вложенного асинхронного кода, используя # 1 или # 3, я не уверен, что выгода перевесит затраты. Что касается ваших предложений, вы можете рассмотреть возможность отправки запроса функции в репозиторий angular, если это важно для вас.
Для получения дополнительной информации я нашел этот источник весьма полезным: https://medium.com/@michaelericksen_12434/angular-asynchronous-test-patterns-and-recipes-202cf7d47ec7 . Надеюсь, это поможет!