ในการทดสอบหน่วยเหตุใดฉันจะสร้างที่เก็บสองครั้ง


10

เมื่อวันก่อนฉันอ่านเกี่ยวกับการทดสอบหน่วยเล็กน้อยและฉันเห็นตัวอย่างที่ผู้คนสร้างส่วนต่อประสานที่เก็บ (เช่นIExampleRepository) จากนั้นสร้างที่เก็บจริง ( public class ExampleRepository : IExampleRepository) และที่เก็บที่จะใช้สำหรับการทดสอบหน่วย ( FakeExampleRepository : IExampleRepository)

ในIExampleRepositoryพวกเขาใช้วิธีการเดียวกันกับในExampleRepositoryแต่ด้วยคำสั่ง Linq ที่แตกต่างกัน

อะไรคือวัตถุประสงค์ตรงนี้? ฉันคิดว่าส่วนหนึ่งของการทดสอบหน่วยของคุณคือตรวจสอบให้แน่ใจว่าวิธีการทำงานถูกต้องหรือไม่ แต่เมื่อฉันใช้แบบสอบถามที่แตกต่างกันสองข้อคำถามหนึ่งสำหรับ 'จริง' และอีกคำถามหนึ่งในการทดสอบการทดสอบมีความรู้สึกมากเพียงใด

คำตอบ:


8

หนึ่งในเป้าหมายของการทดสอบหน่วยคือการทดสอบเพียงครั้งเดียวเช่นคลาสและวิธีการเดียว หากพื้นที่เก็บข้อมูลของตัวเองไม่ได้อยู่ภายใต้การทดสอบแล้วคุณจะเยาะเย้ยนี้ในบางวิธีเพื่อทดสอบตรรกะในวิธีการ / คลาสของคุณ

ที่กล่าวว่าคุณจำเป็นต้องทดสอบด้วยที่เก็บข้อมูล 'จริง' * แต่โดยปกติจะทำในการทดสอบการรวม / ระบบ

* เห็นได้ชัดว่าเหมือนจริงใน repo ตั้งค่าสำหรับการทดสอบหวังว่าไม่เช่นฐานข้อมูลการผลิต


ดังนั้นในการทดสอบหน่วยฉันจะไม่ทดสอบวิธีการของตัวเองเพื่อให้แน่ใจว่ามันคืนค่าที่ถูกต้อง (ตามชุดข้อมูลปลอม / เยาะเย้ย)
jao

ใช่คุณจะทดสอบวิธีการเอง แต่เฉพาะรหัสในวิธีการรหัสในวัตถุอื่น ๆ ควรจะครอบคลุมในการทดสอบหน่วยอื่น ๆ การโต้ตอบของวัตถุหลายรายการควรจะครอบคลุมในการทดสอบการรวมหรือการทดสอบระดับที่สูงขึ้น
jk

1
ตกลงดังนั้นถ้าฉันเข้าใจถูกต้องฉันควรใช้ที่เก็บต้นฉบับเมื่อหน่วยทดสอบที่เก็บ ฉันไม่จำเป็นต้องทดสอบพวกเขาเมื่อฉันกำลังเขียนการทดสอบหน่วยสำหรับตัวควบคุม (ในกรณีของ Asp.Net MVC)
jao

4
@ Theomax ขึ้นอยู่กับบริบท: หากคุณเป็นหน่วยทดสอบส่วนประกอบซอฟต์แวร์ที่ไม่ใช่ของคุณคุณExampleRepositoryควรใช้โปรแกรมจำลอง เหตุผลที่คุณไม่ได้ทดสอบหน่วยเก็บข้อมูล แต่อย่างอื่น
Andres F.

5
@ Theomax เพื่อขยายความคิดเห็นของ AndresF. : หากคุณเป็นหน่วยทดสอบExampleRepositoryให้ใช้ของจริง หากคุณเป็นการทดสอบหน่วยคุณRepositoryControllerควรใช้เฉพาะค่าFakeExampleRepositoryที่ส่งคืนค่าที่ระบุไว้ล่วงหน้าเท่านั้น วิธีนี้ถ้าครีพข้อผิดพลาดในการExampleRepository, เพียงว่าการทดสอบหน่วยจะล้มเหลว - RepositoryController's ทดสอบจะยังคงประสบความสำเร็จเพื่อให้คุณรู้ว่ามีไม่ได้เป็นปัญหาที่มี หากคอนโทรลเลอร์ใช้พื้นที่เก็บข้อมูลจริงพวกเขาทั้งสองจะล้มเหลวและคุณจะไม่รู้ว่าคุณมี 1 ข้อบกพร่องหรือ 2
Izkata

5

ฉันเห็นด้วยกับสองคำตอบจาก jk และ Jan Hudec - พวกเขาให้ข้อมูลที่ดีจริงๆ แต่ฉันคิดว่าฉันจะเพิ่มเล็กน้อย

คำถามแรกของคุณ ("วัตถุประสงค์ที่แท้จริงคืออะไร") มีความสำคัญ ในกรณีที่คุณกำลังอธิบายวัตถุประสงค์ที่แท้จริงคือการทดสอบชั้นเรียนที่ใช้IExampleRepositoryอินเตอร์เฟซที่ไม่ทดสอบการใช้งานพื้นที่เก็บข้อมูล การสร้างFakeExampleRepositoryอนุญาตให้คุณทดสอบคลาสไคลเอ็นต์เหล่านั้นโดยไม่ต้องกังวลเกี่ยวกับรายละเอียดของคลาสที่เก็บจริง

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

การเยาะเย้ย (หรือการขัดลอกเลียนแบบ ... มีความแตกต่างที่เหมาะสม) เป็นเครื่องมือที่ทรงพลังสำหรับการทดสอบหน่วยและ TDD แต่อาจเป็นความเจ็บปวดในการสร้างและบำรุงรักษาการใช้งานเหล่านี้ด้วยตนเอง ดังนั้นภาษาส่วนใหญ่จึงมีห้องสมุดเยาะเย้ยที่จะช่วย เนื่องจากคุณใช้ C # ฉันขอแนะนำMoqเพราะเรียบง่ายและทรงพลังมาก จากนั้นคุณสามารถทดสอบกับอินเทอร์เฟซได้โดยไม่ต้องซ้อนรหัสพิเศษสำหรับการใช้งานจำลอง


the real objective is to test the classes that are utilizing the IExampleRepository interfaceนั่นไม่ใช่ความจริงอย่างเคร่งครัด วัตถุประสงค์คือเพื่อทดสอบโดยอิสระจาก IExampleRepository +1 สำหรับการแนะนำกรอบการแยกที่ดีแม้ว่า
StuperUser

1
ฉันไม่เห็นด้วย. มันไม่ได้เป็นอิสระIExampleRepositoryเพราะชั้นเรียนที่อยู่ภายใต้การทดสอบนั้นเชื่อมโยงกับส่วนต่อประสานนั้น แต่มันเป็นอิสระจากการใช้งานของอินเทอร์เฟซ ฉันจะยอมรับว่าคำอธิบายของฉันอาจใช้กลเม็ดเด็ดพรายเล็กน้อย :)
อัลลัน

5

อะไรคือวัตถุประสงค์ตรงนี้?

การแยกตัว.

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

โดยการสร้างชั้นเรียนปลอมรหัสการผลิตเพียงอย่างเดียวคือชั้นเรียนภายใต้การทดสอบ

หากคุณสร้างที่เก็บข้อมูลปลอมอย่างถูกต้องและการทดสอบล้มเหลวคุณรู้ว่าปัญหานั้นเกิดจากการใช้รหัสภายใต้การทดสอบ สิ่งนี้จะช่วยให้คุณได้รับประโยชน์จากการวินิจฉัยได้ฟรี

ดูกรอบการแยก (เช่นMoqตามที่แนะนำโดย @Allan) เพื่อให้สามารถสร้างของปลอมเหล่านี้ได้อย่างรวดเร็วเพื่อตั้งค่าเงื่อนไขการทดสอบและใช้เพื่อยืนยัน


รายละเอียดเพิ่มเติมเกี่ยวกับ fakes, mocks และ stubs: stackoverflow.com/questions/346372/ …
StuperUser

4

มีเหตุผลสามประการที่คุณอาจต้องการจัดเตรียมอินสแตนซ์จำลองเพื่อทดสอบหน่วย:

  1. คุณต้องการ จำกัด ขอบเขตของการทดสอบเพื่อที่ว่าการทดสอบจะไม่ได้รับผลกระทบจากข้อบกพร่องใน depndee อาจเป็นเพราะมันยังไม่เสร็จหรือไม่เสถียรหรือคุณไม่ต้องการให้บั๊กในคนอื่นมีผลต่อการทดสอบของคุณ
  2. ผู้ติดตั้งมีความซับซ้อนในการตั้งค่า ตัวอย่างเช่นชั้นการเข้าถึงข้อมูลมักถูกเยาะเย้ยเพราะชั้นวางจริงต้องตั้งค่าฐานข้อมูลทดสอบ คุณยังคงต้องทดสอบเลเยอร์การเข้าถึงข้อมูลจริง แต่คุณสามารถ จำกัด การตั้งค่าค่าใช้จ่ายสูงเมื่อทำการดีบั๊กอย่างอื่น
  3. ในการทดสอบว่าคลาสที่พึ่งพานั้นตอบสนองต่อข้อผิดพลาดประเภทต่าง ๆ ได้อย่างถูกต้องคุณต้องมีเวอร์ชันจำลองที่ส่งคืนคำตอบที่ผิดทุกประเภท เนื่องจากโหมดความล้มเหลวจำนวนมากค่อนข้างยากที่จะทำซ้ำ แต่ควรทดสอบ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.