การทดสอบ

วิธีจำลองคำขอเครือข่ายใน Jest

การเยาะเย้ยคำขอเครือข่ายง่ายยิ่งขึ้น

ในปัจจุบัน จำเป็นต้องแก้ไขไลบรารี่เก่าเป็น TS และทำการทดสอบหน่วย หากไลบรารีถูกแก้ไขเป็น TS ก็ยังดีขึ้นอีกเล็กน้อย การทดสอบหน่วยเป็นเพียงการศึกษาในปัจจุบันและจำหน่ายแล้วในขณะนี้ สำหรับผู้เริ่มต้นที่จะเรียนรู้กรอบงาน Jest ฉันคิดว่าสิ่งที่ยุ่งยากกว่าในการทดสอบหน่วยคือการทดสอบคำขอเครือข่าย ดังนั้นให้บันทึกบางวิธีที่ Mock ทิ้ง Axios เพื่อเริ่มต้นคำขอเครือข่าย นี่คือบทความสื่อครั้งที่ 39 ของฉัน

การแนะนำ

ตัวอย่างที่กล่าวถึงในบทความทั้งหมดอยู่ในพื้นที่เก็บข้อมูล jest-mock-server คุณสามารถเริ่มต้นตัวอย่างได้โดยตรงโดยการติดตั้งตัวจัดการแพ็กเกจ เช่น ติดตั้งผ่าน yarn:

$ yarn install

คำสั่งบางคำสั่งระบุไว้ใน package.json ซึ่งมีดังต่อไปนี้:

  • npm run build : คำสั่งบรรจุภัณฑ์ของ rollup
  • npm run test:demo1 : เพียงแค่ mock ไลบรารีคำขอเครือข่ายถูกห่อหุ้มไว้
  • npm run test:demo2 : กรอก mock ให้สมบูรณ์โดยปรับใช้ hook อีกครั้ง
  • npm run test:demo3 : ใช้ไลบรารีใน Jest เพื่อดำเนินการใช้งาน demo2 ให้เสร็จสมบูรณ์
  • npm run test:demo4-5 : เริ่มต้นเซิร์ฟเวอร์ node, proxy คำขอเครือข่ายผ่านพร็อกซีของ axios และส่งต่อไปยังเซิร์ฟเวอร์ node ที่เริ่มต้น ด้วยการตั้งค่าคำขอทดสอบหน่วยและข้อมูลการตอบสนองที่สอดคล้องกัน ความสัมพันธ์ที่สอดคล้องกันจะถูกนำมาใช้เพื่อรับรู้การทดสอบ ซึ่งก็คือ jest-mock-server งานที่เสร็จแล้ว

ที่นี่เราสรุปเลเยอร์ axios ซึ่งใกล้กับฉากจริงมากขึ้น คุณสามารถดูไฟล์ test/demo/wrap-request.ts ได้ ในความเป็นจริง มันเพียงสร้างอินสแตนซ์ axios ภายในและส่งต่อข้อมูลการตอบสนอง

ไฟล์ test/demo/index.ts เพียงส่งออกเมธอด counter โดยที่พารามิเตอร์ทั้งสองนี้ได้รับการประมวลผลในระดับหนึ่งก่อนที่จะเริ่มคำขอเครือข่าย จากนั้นข้อมูลการตอบสนองก็จะถูกประมวลผลในระดับหนึ่ง เพียงเพื่อจำลองการดำเนินการที่เกี่ยวข้อง

ที่นี่ Jest ใช้สภาพแวดล้อมเบราว์เซอร์ที่จำลองโดย JSDOM ไฟล์เริ่มต้น test/config/setup.js ได้รับการกำหนดค่าในแอตทริบิวต์ setupFiles ที่กำหนดค่าใน jest.config.js และ JSDOM ได้รับการกำหนดค่าเริ่มต้นที่นี่

demo1: คำขอเครือข่ายจำลองอย่างง่าย

การประมวลผล mock แบบง่ายดำเนินการใน test/demo1.test.js และคุณสามารถลองเรียกใช้ผ่าน npm run test:demo1 ในความเป็นจริง การดำเนินการ mock จะดำเนินการบนไลบรารี wrap-request ที่ล้อม axios wrap-request จะถูกคอมไพล์เมื่อ Jest เริ่มต้น หลังจากที่ไลบรารีถูกจำลองที่นี่ ไฟล์ทั้งหมดที่นำเข้ามาในไลบรารีหลังจากนั้นจะได้รับอ็อบเจ็กต์ที่ถูกจำลอง กล่าวอีกนัยหนึ่ง เราสามารถคิดว่าไลบรารีนี้ถูกเขียนใหม่แล้ว และวิธีการหลังจากเขียนใหม่ทั้งหมดคือ JEST's Mock Functions คุณสามารถใช้ฟังก์ชันต่างๆ เช่น mockReturnValue สำหรับการจำลองข้อมูลได้ สำหรับ Mock Functions โปรดดูที่ ลิงก์ นี้

ที่นี่เราได้กรอก Mock ของค่าที่ส่งคืนแล้ว ซึ่งหมายความว่าเราสามารถควบคุมค่าที่ส่งคืนโดย request ในไลบรารี wrap-request ได้ อย่างไรก็ตาม มีการกล่าวถึงก่อนหน้านี้ว่ามีกระบวนการบางอย่างสำหรับพารามิเตอร์ที่เข้ามาด้วย เราไม่ได้ยืนยันใดๆ เกี่ยวกับเนื้อหาในส่วนนี้ ดังนั้นเราจึงจำเป็นต้องพยายามจัดการกับเรื่องนี้ด้วย

demo2: คำขอเครือข่ายขอ

demo2 สามารถลองเรียกใช้ผ่าน npm run test:demo2 ได้ ตามที่กล่าวไว้ข้างต้น เราสามารถจัดการกับค่าที่ส่งคืนได้ แต่ไม่มีวิธีใดที่จะยืนยันว่าพารามิเตอร์อินพุตได้รับการประมวลผลอย่างถูกต้องหรือไม่ ดังนั้นเราจึงจำเป็นต้องจัดการกับสถานการณ์นี้ โชคดีที่ Jest มีวิธีการนำไลบรารีฟังก์ชันที่ถูกจำลองไปใช้โดยตรง ดังนั้น Jest ยังมีเมธอด mockImplementation ซึ่งใช้ใน demo3 อีกด้วย ที่นี่เราได้เขียนไลบรารีฟังก์ชันที่จำลองขึ้นใหม่ นอกจากนี้เรายังสามารถใช้ jest.fn เพื่อทำให้ Implementations สมบูรณ์ได้ ที่นี่เราเขียนฟังก์ชัน hook ก่อนส่งคืน จากนั้นใช้การยืนยันหรือระบุค่าส่งคืนในแต่ละ test ด้วยวิธีนี้ ปัญหาข้างต้นสามารถแก้ไขได้ ซึ่งจริงๆ แล้วคือการรับรู้ mockImplementation จาก Mock Functionsใน Jest

demo3: ใช้ mockImplementation ของ Jest

demo3 สามารถลองเรียกใช้ผ่าน npm run test:demo3 ได้ ตัวอย่างใน demo2 จริงๆ แล้วซับซ้อนในการเขียน ใน Jest, Mock Functionsมีการใช้งาน mockImplementation ซึ่งสามารถใช้ได้โดยตรง

demo4–5: เริ่มต้นคำขอเครือข่ายจริงๆ

demo4 และ demo5 สามารถลองเรียกใช้ผ่าน npm run test:demo4–5 ได้ ด้วยวิธีนี้จะมีการร้องขอข้อมูลจริง ที่นี่ axios พร็อกซีจะถูกใช้เพื่อส่งต่อคำขอข้อมูลภายในไปยังพอร์ตเซิร์ฟเวอร์ที่ระบุ ดังนั้น เซิร์ฟเวอร์จะเริ่มทำงานในเครื่องด้วย และทำการทดสอบโดยการระบุข้อมูลคำขอและการตอบกลับที่เกี่ยวข้องกับ path ที่เกี่ยวข้อง หากข้อมูลที่ร้องขอไม่ถูกต้อง ข้อมูลการตอบกลับที่เกี่ยวข้องจะไม่ได้รับการจับคู่ตามปกติ ดังนั้นคำขอจะส่งคืน 500 โดยตรง หากข้อมูลตอบกลับไม่ถูกต้อง ข้อมูลดังกล่าวจะถูกบันทึกระหว่างการยืนยันด้วย ในไลบรารี jest-mock-server ก่อนอื่น เราต้องระบุไฟล์สามไฟล์ซึ่งสอดคล้องกับวงจรชีวิตสามรอบที่แต่ละไฟล์ทดสอบหน่วยจะต้องดำเนินการก่อนเริ่มต้นระบบ การทดสอบ Jest จะดำเนินการก่อนรอบชีวิตสามรอบ และรอบชีวิตทั้งสามจะดำเนินการหลังจากการทดสอบ Jest เสร็จสิ้น ไฟล์สามไฟล์ที่เราต้องระบุคือรายการการกำหนดค่า setupFiles, globalSetup และ globalTeardown ของไฟล์การกำหนดค่า jest.config.js

ก่อนอื่นเราจะเริ่มต้นด้วย setupFiles นอกจากการเริ่มต้น JSDOM แล้ว เรายังต้องใช้งานพร็อกซีเริ่มต้นที่ axios ด้วย เนื่องจากโซลูชันที่นำมาใช้คือการใช้ proxy จาก axios เพื่อส่งต่อคำขอข้อมูล ดังนั้นจึงจำเป็นต้องตั้งค่าพร็อกซีไว้ที่แถวหน้าของการทดสอบหน่วย

เมื่อเราตั้งค่าไฟล์ด้านบนไว้ในโฟลเดอร์ test/config แล้ว เราจะต้องเพิ่มไฟล์อีกสองไฟล์ในนั้น ซึ่งได้แก่ globalSetup และ globalTeardown ไฟล์ทั้งสองนี้อ้างอิงถึงการดำเนินการที่ดำเนินการก่อนที่การทดสอบหน่วย Jest จะเริ่มต้นและหลังจากการทดสอบทั้งหมดเสร็จสิ้น เราใส่การดำเนินการเริ่มต้นและปิดเซิร์ฟเวอร์ไว้ในไฟล์ทั้งสองนี้

โปรดทราบว่าไฟล์ที่ทำงานในทั้งสองไฟล์นี้เป็นไฟล์ contex อิสระที่แยกจากกัน ซึ่งไม่มีส่วนเกี่ยวข้องกับ contex ของการทดสอบหน่วยใดๆ รวมถึงไฟล์ที่ระบุโดยรายการการกำหนดค่า setupFiles ดังนั้นข้อมูลทั้งหมดที่นี่จึงระบุไว้ในไฟล์กำหนดค่าหรือเป็นการส่งระหว่างพอร์ตเซิร์ฟเวอร์ผ่านเครือข่าย

สำหรับข้อมูลพอร์ตการกำหนดค่าและชื่อโดเมน ให้ใส่ลงในฟิลด์ globals ใน jest.config.js โดยตรง สำหรับรายการการกำหนดค่า debug ขอแนะนำให้ใช้ร่วมกับ test.only

ขณะนี้อาจมีข้อเสนอแนะว่าเหตุใดเซิร์ฟเวอร์จึงไม่ควรเริ่มต้นและปิดระบบในวงจรชีวิต beforeAll และ afterAll ของไฟล์ทดสอบแต่ละไฟล์ ดังนั้นฉันจึงได้ลองใช้วิธีแก้ปัญหานี้แล้ว ในโซลูชันนี้ สำหรับไฟล์ทดสอบแต่ละไฟล์ เซิร์ฟเวอร์จะเริ่มทำงานแล้วปิดระบบ ดังนั้นวิธีแก้ปัญหานี้จึงค่อนข้างใช้เวลานาน แต่ในทางทฤษฎีแล้ว วิธีแก้ปัญหานี้ก็สมเหตุสมผล ท้ายที่สุดแล้ว เป็นความจริงที่ว่าจำเป็นต้องมีการแยกข้อมูล แต่มีปัญหาเมื่อปิด afterAll ไม่ได้ปิดเซิร์ฟเวอร์และการยึดครองพอร์ตจริง ๆ เนื่องจากการเรียกเมธอด close เมื่อเซิร์ฟเวอร์ node ถูกปิด เมื่อafterAll ถูกปิด มันเพิ่งหยุดการประมวลผลคำขอ แต่พอร์ตยังคงถูกครอบครอง เมื่อไฟล์ทดสอบหน่วยที่สองเริ่มทำงาน จะมีข้อยกเว้นว่าพอร์ตนั้นถูกใช้อยู่ แม้ว่าฉันจะลองวิธีแก้ปัญหาบางอย่างแล้ว แต่ก็ไม่เหมาะเพราะบางครั้งพอร์ตยังถูกครอบครอง โดยเฉพาะอย่างยิ่งเมื่อมีการเรียกใช้ node เป็นครั้งแรกหลังจากเปิดเครื่อง ความน่าจะเป็นที่จะเกิดความผิดปกติค่อนข้างสูง ผลที่ได้จึงไม่ค่อยน่าพอใจนัก ในท้ายที่สุด มีการใช้แผนการแยกเดี่ยวที่สมบูรณ์ สำหรับปัญหาที่เกี่ยวข้องโดยเฉพาะ โปรดดูที่ "ลิงก์" นี้

เนื่องจากเราใช้โซลูชันที่แยกเดี่ยวกันโดยสิ้นเชิง จึงมีเพียงสองตัวเลือกเท่านั้นที่เราต้องการส่งข้อมูลคำขอและข้อมูลตอบกลับสำหรับคำขอทดสอบ ทั้งสองวิธีคือเมื่อเซิร์ฟเวอร์เริ่มทำงาน ข้อมูลทั้งหมดจะถูกระบุในไฟล์ test/config/global-setup.js หรือข้อมูลถูกส่งผ่านเครือข่ายเมื่อเซิร์ฟเวอร์ทำงาน มีการระบุเส้นทาง และคำขอเครือข่ายของเส้นทางจะนำข้อมูลและข้อมูล คำขอจะถูกระบุในการปิดเซิร์ฟเวอร์ ดังนั้นจึงรองรับทั้งสองตัวเลือกที่นี่ ฉันคิดว่าการระบุข้อมูลของคุณเองในไฟล์ทดสอบแต่ละหน่วยนั้นเหมาะสมกว่า ดังนั้นนี่เป็นเพียงตัวอย่างหนึ่งของการระบุข้อมูลที่จะทดสอบในไฟล์ทดสอบหน่วย เกี่ยวกับข้อมูลที่จะทดสอบ มีการระบุประเภท DataMapper เพื่อลดข้อยกเว้นที่เกิดจากข้อผิดพลาดประเภท ดังนั้นจึงมีการแสดงตัวอย่างชุดข้อมูลสองชุดที่นี่ นอกจากนี้ ยังรองรับนิพจน์ทั่วไปเมื่อจับคู่ query และ data โครงสร้างของประเภท DataMapper นั้นค่อนข้างมาตรฐาน

ในการทดสอบสองหน่วยด้านล่าง ข้อมูลที่จะทดสอบระบุไว้ใน beforeAll โปรดทราบว่า beforeAll ส่งคืน setSuitesData(data) เนื่องจากการทดสอบหน่วยจะดำเนินการหลังจากตั้งค่าข้อมูลและการตอบสนองสำเร็จ ตามด้วยคำขอปกติและการตอบกลับว่าการทดสอบการยืนยันนั้นถูกต้องหรือไม่