Pengujian Angular 2 - Panggilan fungsi Async - kapan harus digunakan

89

Kapan Anda menggunakan fungsi async di TestBed saat menguji di Angular 2?

Kapan Anda menggunakan ini?

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

Dan kapan Anda menggunakan ini?

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

Adakah yang bisa mencerahkan saya tentang ini?

xiotee
sumber

Jawaban:

97

asynctidak akan mengizinkan pengujian berikutnya untuk memulai hingga asyncmenyelesaikan semua tugasnya. Apa yang asyncdilakukan adalah membungkus callback dalam Zona, di mana semua tugas asinkron (misalnya setTimeout) dilacak. Setelah semua tugas asinkron selesai, maka asyncselesai.

Jika Anda pernah bekerja dengan Jasmine di luar Angular, Anda mungkin pernah melihat donediteruskan ke panggilan balik

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

Di sini, ini Jasmine asli, di mana kami memberi tahu Jasmine bahwa tes ini harus menunda penyelesaian sampai kami menelepon done(). Jika kami tidak menelepon done()dan malah melakukan ini:

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

Pengujian akan selesai bahkan sebelum ekspektasi, karena promise diselesaikan setelah pengujian selesai menjalankan tugas sinkron.

Dengan Angular (di lingkungan Jasmine), Angular akan benar-benar memanggil di donebelakang layar saat kita menggunakan async. Ini akan melacak semua tugas asinkron di Zone, dan ketika semuanya selesai, doneakan dipanggil di belakang layar.

Dalam kasus khusus Anda dengan TestBedkonfigurasi, Anda akan menggunakan ini secara umum bila Anda mau compileComponents. Saya jarang mengalami situasi di mana saya harus menyebutnya sebaliknya

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

Saat menguji komponen yang menggunakan templateUrl(jika Anda tidak menggunakan webpack), Angular perlu membuat permintaan XHR untuk mendapatkan template, sehingga kompilasi komponen akan asinkron. Jadi kita harus menunggu sampai selesai sebelum melanjutkan pengujian.

Paul Samsotha
sumber
1
Jawaban bagus @peeskillet. Hanya untuk memastikan saya memahaminya: Bila Anda memiliki template sebaris, asynctidak perlu. Saat Anda menggunakan templateUrl, itu. Namun, memasukkan asynctidak akan "merusak" komponen template-sebaris. Apakah menurut Anda aman untuk mengatakan bahwa satu default dapat digunakan asyncuntuk setiap pengujian?
vince
2
@vincecampanale TemplateUrl hanya penting selama konfigurasi di beforeEach. Dalam hal ini Anda perlu menelepon compileComponents. Tidak ada hubungannya dengan penggunaan asyncpada setiap tes jika itu yang Anda tanyakan. Sejauh aman (kapan Anda harus menelepon compileComponents), lihat Kapan saya harus menelepon compileComponents
Paul Samsotha
2
@vincecampanale Tidak selalu demikian yang Anda inginkan sebelum pengujian. Terkadang Anda mungkin ingin memanggilnya setelah Anda melakukan inisialisasi. Anda perlu memahami apa sebenarnya panggilan itu. Sebagian besar waktu seharusnya baik-baik saja. Tetapi saya pribadi tidak suka mereka mengambil keputusan itu sendiri. Tetapi saya melihat banyak orang mengalami masalah di mana mereka lupa menyebutnya, dan mereka bertanya-tanya mengapa ada yang tidak berhasil. Jadi mungkin lebih baik mereka membuat panggilan. Lokasinya mungkin bisa diperdebatkan, tetapi setidaknya mereka menyebutnya
Paul Samsotha
2
@vincecampanale Umumnya saat Anda ingin tampilan (ulang) dirender adalah saat Anda harus memanggilnya. Misalnya Buat Komponen -> tampilan render. Tetapi jika Anda ingin menginisialisasi sesuatu terlebih dahulu seperti Create Component -> ubah nilai dalam komponen yang digunakan untuk membuat -> membuat tampilan. Itulah yang saya maksud dengan mungkin Anda ingin menginisialisasi sesuatu terlebih dahulu
Paul Samsotha
1
Oh dan satu hal lagi. Pertama kali Anda memanggilnya, adalah ketika ngOnInitkomponen dipanggil. Terkadang hal ini penting saat pengujian
Paul Samsotha
26

Saat Anda membuat panggilan asinkron dalam pengujian Anda, fungsi pengujian yang sebenarnya selesai sebelum panggilan asinkron selesai. Saat Anda perlu memverifikasi beberapa status saat panggilan selesai (yang biasanya terjadi), framework pengujian akan melaporkan pengujian sebagai selesai sementara masih ada pekerjaan asinkron yang sedang berlangsung.

Dengan menggunakan, async(...)Anda memberi tahu framework pengujian untuk menunggu hingga janji pengembalian atau observable selesai sebelum memperlakukan pengujian sebagai selesai.

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);
  });
}));

Kode yang diteruskan ke then(...)akan dijalankan setelah fungsi pengujian itu sendiri selesai. Dengan async()Anda membuat kerangka pengujian sadar, bahwa ia perlu menunggu janji dan observable selesai sebelum memperlakukan pengujian sebagai selesai.

Lihat juga

Günter Zöchbauer
sumber