การใช้การฉีดพึ่งพา (DI) จำเป็นสำหรับการทดสอบหน่วยหรือไม่
ฉันไม่สามารถคิดวิธีอื่นในการแยกรหัสเพื่อให้สามารถทดสอบได้ นอกจากนี้ตัวอย่างทั้งหมดที่ฉันเคยเห็นใช้รูปแบบนี้ นั่นเป็นเพราะมันเป็นทางเลือกเดียวที่ทำงานได้หรือมีทางเลือกอื่น ๆ ?
การใช้การฉีดพึ่งพา (DI) จำเป็นสำหรับการทดสอบหน่วยหรือไม่
ฉันไม่สามารถคิดวิธีอื่นในการแยกรหัสเพื่อให้สามารถทดสอบได้ นอกจากนี้ตัวอย่างทั้งหมดที่ฉันเคยเห็นใช้รูปแบบนี้ นั่นเป็นเพราะมันเป็นทางเลือกเดียวที่ทำงานได้หรือมีทางเลือกอื่น ๆ ?
คำตอบ:
DI ทำให้การทดสอบหน่วยง่ายขึ้นมาก แต่คุณยังสามารถเขียนการทดสอบหน่วยโดยไม่ต้อง DI มีการเขียนการทดสอบหน่วยจำนวนมากแล้วก่อนที่ DI จะแพร่หลาย (แน่นอนว่าเทคนิคที่ใช้เหล่านี้เหมือนกันหรือคล้ายกับ DI โดยไม่ทราบว่ามันมีชื่อแฟนซี :-)
ฉันเองเคยใช้อินเทอร์เฟซและโรงงานมาก่อนเรียนรู้เกี่ยวกับ DI ชื่อคลาสจริงจากโรงงานอาจถูกอ่านจากไฟล์ปรับแต่งหรือส่งผ่านไปยัง SUT เพื่อเป็นอาร์กิวเมนต์
อีกวิธีคือใช้ซิงเกิลตัน (หรือข้อมูลทั่วโลกที่เข้าถึงได้โดยทั่วไป) ใช่ฉันรู้ว่าไม่แนะนำโดยทั่วไป (รวมถึงตัวเอง) โดยทั่วไป ยังคงสามารถใช้งานได้ในสถานการณ์ที่เฉพาะเจาะจงโดยเฉพาะอย่างยิ่งหากซิงเกิลตันมีข้อมูลการกำหนดค่าสแตติกซึ่งไม่เฉพาะกรณีทดสอบ แต่แตกต่างกันระหว่างการผลิตและสภาพแวดล้อมการทดสอบ แน่นอนว่ามันมีปัญหาที่รู้จักดังนั้น DI จะดีกว่าถ้าคุณสามารถใช้มันได้ แต่บ่อยครั้ง (เช่นในระบบดั้งเดิม) คุณทำไม่ได้
เมื่อพูดถึงการทำงานอย่างมีประสิทธิภาพด้วยรหัสมรดกอธิบายเทคนิคมากมายในการรับรหัสดั้งเดิมที่ครอบคลุมโดยการทดสอบ หลายสิ่งเหล่านี้ไม่ดีและไม่ได้มีไว้สำหรับแก้ปัญหาระยะยาว แต่มันช่วยให้คุณสร้างการทดสอบหน่วยที่มีค่าเป็นครั้งแรกในระบบที่ไม่สามารถทดสอบได้ ... ซึ่งช่วยให้คุณสามารถเริ่มการปรับโครงสร้างใหม่และในที่สุด (ในหมู่อื่น ๆ ) แนะนำ DI
การแยกตัวเป็นสิ่งจำเป็นสำหรับการทดสอบหน่วย DI เป็นวิธีที่ดีในการบรรลุการแยกส่วน
คุณสามารถแยกการพึ่งพาได้โดยไม่ต้องใช้ DI ทั้งนี้ขึ้นอยู่กับเทคโนโลยีที่คุณใช้ ตัวอย่างเช่นในโลก. NET โมลช่วยให้คุณสามารถแยกการพึ่งพาโดยไม่มีรูปแบบ DI
ที่กล่าวว่าฉันเชื่อว่ากรอบการแยกเหล่านี้ถูกเขียนและมีไว้สำหรับสถานการณ์ในรหัสของคุณที่มีการอ้างอิงภายนอก (ระบบไฟล์ฐานข้อมูล ฯลฯ ) นั่นคือความจริงที่ว่าคน ๆ หนึ่งสามารถทำได้ไม่ได้หมายความว่าเขาหรือเธอควรจะทำ
การฉีดพึ่งพาช่วยให้การทดสอบหน่วย แต่มันยังอนุญาตให้มีการปรับเปลี่ยนพฤติกรรมของวัตถุโดยไม่ต้องเปลี่ยนรหัสของวัตถุนั้น (หลักการเปิด / ปิด) ดังนั้นจึงไม่ใช่แค่รหัสที่สามารถทดสอบได้ แต่เป็นรหัสที่ยืดหยุ่นซึ่งเป็นผลลัพธ์ ฉันพบโดยทั่วไปแล้วว่ามีความสัมพันธ์อย่างมากระหว่างรหัสที่สามารถบำรุงรักษา / ยืดหยุ่นและรหัสที่ทดสอบได้
ไม่ DI ไม่จำเป็นสำหรับการทดสอบหน่วย แต่ช่วยได้มาก
คุณสามารถใช้โรงงานหรือตัวระบุตำแหน่งและทดสอบตามที่คุณต้องการกับ DI (ไม่สวยงามและต้องมีการตั้งค่าเพิ่มเติม)
นอกจากนี้Mock Objectsจะมีความสำคัญในระบบเดิมที่การโทรจำนวนมากถูกมอบหมายให้ทำงานแทนการพึ่งพา (วัตถุจำลองสามารถนำไปใช้อย่างกว้างขวางในการตั้งค่าที่เหมาะสมเช่นกัน)
อาจมีการตั้งค่าที่การทดสอบแทบจะเป็นไปไม่ได้ แต่นี่ไม่ได้ขึ้นอยู่กับว่าจะใช้การฉีดแบบพึ่งพาหรือไม่
ไม่มีการฉีดพึ่งพาไม่ได้เป็นสิ่งจำเป็นสำหรับการทดสอบหน่วย
การฉีดพึ่งพาช่วยถ้าคุณมีคลาสที่ต้องการอินสแตนซ์ของคลาสที่พึ่งพาเพื่อทำการประมวลผลย่อยบางอย่าง แทนที่จะเป็น DI คุณสามารถแยกตรรกะของวิธีการทางธุรกิจลงในส่วนรับข้อมูล (ที่ไม่สามารถทดสอบได้) และส่วนการคำนวณที่สามารถทดสอบหน่วยได้
ตัวอย่าง (ใช้ DI) การใช้งานนี้ขึ้นอยู่กับพนักงานบัญชี ...
bool hasPermissionToTransferMoney(Employee employee, Account from, Account to, Money amount)
{
if (amount > 100 && employee.isStudent())
return false;
if (to.getOwner().getFamiliyName() == employee.getFamilyName() && ...
return false; // cannot transfer money to himself;
...
}
หลังจากแยกการรวบรวมข้อมูลและการคำนวณ:
bool hasPermissionToTransferMoney(Employee employee, Account from, Account to, Money amount)
{
return hasPermissionToTransferMoney(employee.isStudent(), employee.getFamilyName(), to.getOwner().getFamilyName(), ...);
}
// the actual permission calculation
static bool hasPermissionToTransferMoney(boolean isStudent, string employeeFamilyName, string receiverFamilyName, ...)
if (amount > 100 && isStudent)
return false;
if (receiverFamilyName == employeeFamiliyName && ...
return false; // cannot transfer money to himself
...
}
ส่วนการคำนวณสามารถทดสอบได้ง่ายโดยไม่ต้องพึ่งพาการฉีด
การฉีดพึ่งพาไม่จำเป็นสำหรับการทดสอบหน่วย
การผกผันของการควบคุมในทางกลับกันเป็นสิ่งสำคัญเมื่อคุณต้องการสลับการใช้งานหนึ่งไปยังอีก
ใช่มีทางเลือกอื่นสำหรับการใช้ DI สำหรับการแยก
ทางเลือกหนึ่งคือใช้โรงงานหรือ ServiceLocator ซึ่งสามารถกำหนดค่าจากการทดสอบเพื่อส่งคืนวัตถุจำลองแทนวัตถุจริง
อีกประการหนึ่งคือการใช้กรอบการแยกที่เหมาะสมหรือเครื่องมือเยาะเย้ย มีเครื่องมือดังกล่าวสำหรับภาษาการเขียนโปรแกรมที่ทันสมัยทุกภาษา (สำหรับ Java, C #, Ruby และ Python อย่างน้อย) พวกเขาสามารถแยกคลาสที่ถูกทดสอบจากการใช้คลาส / ประเภทอื่น ๆ แม้ว่าคลาสที่ทดสอบโดยตรงจะสร้างการพึ่งพาได้ทันที