Тестування Angular 2 - Виклик функції асинхронізації - коли використовувати


86

Коли ви використовуєте функцію асинхронізації в TestBed під час тестування в Angular 2?

Коли ви використовуєте це?

 beforeEach(() => {
        TestBed.configureTestingModule({
            declarations: [MyModule],
            schemas: [NO_ERRORS_SCHEMA],
        });
    });

І коли ви цим користуєтесь?

beforeEach(async(() => {
    TestBed.configureTestingModule({
        declarations: [MyModule],
        schemas: [NO_ERRORS_SCHEMA],
    });
}));

Хто-небудь може мене просвітлити в цьому?

Відповіді:


95

asyncне дозволить розпочати наступний тест, поки не виконає asyncвсі свої завдання. Що asyncозначає обернути зворотний виклик у Зону, де setTimeoutвідстежуються всі асинхронні завдання (наприклад ). Як тільки всі асинхронні завдання будуть завершені, тоді asyncвиконується.

Якщо ви коли-небудь працювали з Жасмином за межами Angular, можливо, ви бачили, doneяк передавали зворотний дзвінок

it('..', function(done) {
  someAsyncAction().then(() => {
    expect(something).toBe(something);
    done();
  });
});

Ось це рідна жасмин, де ми говоримо Жасмин, що цей тест повинен затримати завершення, поки ми не зателефонуємо done(). Якби ми не зателефонували done()і замість цього зробили це:

it('..', function() {
  someAsyncAction().then(() => {
    expect(something).toBe(something);
  });
});

Тест завершиться ще до очікування, оскільки обіцянка вирішується після закінчення тесту, виконуючи синхронні завдання.

З Angular (в середовищі жасмину), Angular насправді буде дзвонити doneза куліси, коли ми використовуємо async. Він буде відстежувати всі асинхронні завдання в Зоні, і коли вони будуть закінчені, doneбуде викликаний за кадром.

У вашому конкретному випадку з TestBedконфігурацією ви зазвичай використовуєте це, коли хочете compileComponents. Я рідко потрапляю в ситуацію, коли мені доводиться називати це інакше

beforeEach(async(() => {
   TestBed.configureTestingModule({
     declarations: [MyModule],
     schemas: [NO_ERRORS_SCHEMA],
   })
   .compileComponent().then(() => {
      fixture = TestBed.createComponent(TestComponent);
   });
}));

При тестуванні компонента, який використовує templateUrl (якщо ви не використовуєте веб-пакет), тоді Angular повинен зробити запит XHR, щоб отримати шаблон, тому компіляція компонента буде асинхронною. Тому нам слід почекати, поки він не вирішиться, перш ніж продовжувати тестування.


Чудова відповідь @peeskillet. Тільки для того, щоб переконатися, що я це розумію: коли у вас є вбудований шаблон, asyncце не обов’язково. Коли ви використовуєте templateUrl, це так. Однак включення asyncне буде "зламати" компонент вбудованого шаблону. Як ви вважаєте, чи можна з упевненістю сказати, що можна просто за замовчуванням використовувати asyncдля кожного тесту?
Вінс,

2
@vincecampanale ШаблонUrl має значення лише під час конфігурації в beforeEach. У такому випадку вам потрібно зателефонувати compileComponents. Це не має нічого спільного з використанням asyncкожного тесту, якщо це те, про що ви просите. Наскільки це безпечно (коли вам слід зателефонувати compileComponents), дивіться, коли я повинен зателефонувати compileComponents
Пол Самсота

2
@vincecampanale Не завжди так хочеться, щоб його викликали перед тестом. Іноді вам може знадобитися зателефонувати йому після певної ініціалізації. Ви повинні розуміти, що насправді це викликає. У більшості випадків це все має бути нормально. Але мені особисто не подобається, що вони взяли на себе рішення прийняти це рішення. Але я бачу, що багато людей стикаються з проблемою, коли забувають її називати, і дивуються, чому щось не працює. Тож, можливо, краще, щоб вони справді генерували дзвінок. Місце може бути спірним, але принаймні вони називають це
Пол Самсота

2
@vincecampanale Як правило, коли ви хочете, щоб вигляд (повторно) відображався, це коли вам слід його викликати. Наприклад, Створити компонент -> подання візуалізації. Але якщо ви хочете спочатку ініціалізувати щось на зразок Створити компонент -> змінити значення в компоненті, який використовується для відтворення -> подання подання. Ось що я маю на увазі під тим, що, можливо, ти хочеш спочатку щось ініціалізувати
Пол Самсота,

1
Ох і ще одна річ. Перший раз, коли ви викликаєте його, це коли ngOnInitвикликається компонент. Іноді це має значення під час тестування
Пол Самсота

26

Коли ви здійснюєте асинхронний виклик у своєму тесті, фактична тестова функція завершується до завершення асинхронного виклику. Коли вам потрібно перевірити якийсь стан, коли виклик був завершений (як правило, це трапляється), тоді тестовий фреймворк повідомляє про тестування як про завершене, поки ще триває робота з асинхронізацією.

Під час використання async(...)ви кажете тестовій структурі почекати, поки не буде завершено обіцянку повернення або спостережуване, перш ніж розглядати тест як завершений.

it('should show quote after getQuote promise (async)', async(() => {
  fixture.detectChanges();

  fixture.whenStable().then(() => { // wait for async getQuote
    fixture.detectChanges();        // update view with quote
    expect(el.textContent).toBe(testQuote);
  });
}));

Код, який передається, then(...)буде виконаний після завершення самої функції тесту. З async()вами зробити тест рамки знають, що потрібно чекати обіцянок та спостережуваних завершити до лікування тестів завершених.

Дивіться також

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.