การทดสอบเชิงมุม 2 - การเรียกใช้ฟังก์ชัน Async - เมื่อจะใช้


89

คุณใช้ฟังก์ชัน async ในTestBedเมื่อใดเมื่อทำการทดสอบใน Angular 2

คุณใช้สิ่งนี้เมื่อใด

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

และคุณใช้สิ่งนี้เมื่อใด?

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

ใครสามารถให้ความกระจ่างฉันเกี่ยวกับเรื่องนี้?

คำตอบ:


97

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

การทดสอบจะเสร็จสมบูรณ์ก่อนที่จะเกิดความคาดหมายเนื่องจากสัญญาจะแก้ไขหลังจากการทดสอบเสร็จสิ้นในการดำเนินการงานซิงโครนัส

ด้วยเชิงมุม (ในสภาพแวดล้อมที่จัสมิน) เชิงมุมจริงจะเรียกเบื้องหลังเมื่อเราใช้done asyncมันจะติดตามงานอะซิงโครนัสทั้งหมดในโซนและเมื่อเสร็จสิ้นทั้งหมดdoneจะถูกเรียกเบื้องหลัง

โดยเฉพาะในกรณีของคุณด้วยการกำหนดค่าที่คุณจะใช้โดยทั่วไปเมื่อคุณต้องการTestBed compileComponentsฉันไม่ค่อยเจอสถานการณ์ที่ฉันต้องเรียกมันว่าเป็นอย่างอื่น

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

เมื่อทดสอบคอมโพเนนต์ที่ใช้templateUrl(หากคุณไม่ได้ใช้ webpack) Angular จำเป็นต้องส่งคำขอ XHR เพื่อรับเทมเพลตดังนั้นการคอมไพล์ของคอมโพเนนต์จะเป็นแบบอะซิงโครนัส ดังนั้นเราควรรอจนกว่าจะแก้ไขก่อนที่จะทำการทดสอบต่อไป


1
คำตอบที่ยอดเยี่ยม @peeskillet เพื่อให้แน่ใจว่าฉันเข้าใจ: เมื่อคุณมีเทมเพลตแบบอินไลน์asyncก็ไม่จำเป็น เมื่อคุณกำลังใช้templateUrlงานอยู่ อย่างไรก็ตามการรวมasyncจะไม่ "ทำลาย" องค์ประกอบอินไลน์ - เทมเพลต คุณคิดว่าปลอดภัยหรือไม่ที่จะบอกว่าเราสามารถใช้asyncสำหรับการทดสอบทุกครั้งได้
วินซ์

2
@vincecampanale templateUrl มีความสำคัญเฉพาะระหว่างการกำหนดค่าใน beforeEach ซึ่งในกรณีนี้คุณต้องโทรcompileComponents. ไม่มีอะไรเกี่ยวข้องกับการใช้asyncในการทดสอบแต่ละครั้งหากนั่นคือสิ่งที่คุณต้องการ เท่าที่จะปลอดภัย (เมื่อคุณควรโทรcompileComponents) โปรดดูที่ฉันควรจะโทรหา compileComponents
Paul Samsotha

2
@vincecampanale ไม่ใช่กรณีที่คุณต้องการให้เรียกก่อนการทดสอบเสมอไป บางครั้งคุณอาจต้องการเรียกมันว่าหลังจากเริ่มต้นบางอย่างแล้ว คุณต้องเข้าใจว่าการเรียกมันทำอะไรได้จริง เวลาส่วนใหญ่มันควรจะโอเค แต่โดยส่วนตัวแล้วฉันไม่ชอบที่พวกเขาเอามันมาตัดสินใจแบบนั้น แต่ฉันเห็นผู้คนจำนวนมากประสบปัญหาที่พวกเขาลืมเรียกมันและพวกเขาสงสัยว่าทำไมบางอย่างถึงไม่ได้ผล ดังนั้นอาจจะดีกว่าถ้าพวกเขาสร้างการโทร สถานที่อาจเป็นที่ถกเถียงกัน แต่อย่างน้อยพวกเขาก็เรียกมันว่า
Paul Samsotha

2
@vincecampanale โดยทั่วไปเมื่อคุณต้องการให้มุมมอง (re) แสดงผลคือเวลาที่คุณควรเรียกมัน ตัวอย่างเช่น Create Component -> render view แต่ถ้าคุณต้องการเริ่มต้นบางสิ่งก่อนเช่น Create Component -> change value in component that is used to render -> render view. นั่นคือสิ่งที่ฉันหมายถึงบางทีคุณอาจต้องการเริ่มต้นบางสิ่งก่อน
Paul Samsotha

1
อ้อและอีกอย่าง ครั้งแรกที่คุณเรียกมันคือเมื่อngOnInitอยู่ในส่วนประกอบถูกเรียก บางครั้งสิ่งนี้ก็สำคัญเมื่อทำการทดสอบ
Paul Samsotha

26

เมื่อคุณทำการโทรแบบ async ในการทดสอบของคุณฟังก์ชันทดสอบจริงจะเสร็จสมบูรณ์ก่อนที่การเรียก async จะเสร็จสมบูรณ์ เมื่อคุณต้องการตรวจสอบสถานะบางอย่างเมื่อการโทรเสร็จสิ้น (ซึ่งโดยปกติจะเป็นกรณีนี้) กรอบการทดสอบจะรายงานการทดสอบว่าเสร็จสิ้นในขณะที่ยังคงมีการทำงานแบบ async อยู่

เมื่อใช้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()คุณทำให้กรอบการทดสอบทราบแล้วว่าจำเป็นต้องรอให้สัญญาและข้อสังเกตต่างๆดำเนินการให้เสร็จสิ้นก่อนจึงจะถือว่าการทดสอบเสร็จสมบูรณ์

ดูสิ่งนี้ด้วย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.