ฉันจะทดสอบวิธีการเก็บข้อมูลที่นำไปใช้กับ Entity Framework ได้อย่างไร

ฉันมีวิธีการเช่นนี้ในชั้นพื้นที่เก็บข้อมูลของฉัน:

public IEnumerable<User> GetActiveUsers()
{
    return dbContext.Users
           .Where(u => u.IsActive)
           .OrderBy(u => u.Name)
           .ToList();
}

ฉันควรทดสอบวิธีนี้ด้วยการเยาะเย้ย DbContext หรือฉันควรทดสอบกับฐานข้อมูลจริงหรือไม่

ฉันรู้ว่ามันหยุดเป็นการทดสอบ "หน่วย" เมื่อฉันใช้ฐานข้อมูลจริง แต่ฉันไม่เห็นค่าในการเยาะเย้ย DbContext เพื่อทดสอบวิธีการเก็บข้อมูลของฉันซึ่งมีตรรกะบางเฉียบและมักจะเรียกวิธีการของ EF โดยตรง

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


person Saravana    schedule 05.04.2014    source แหล่งที่มา
comment
ฉันไม่ได้ทำกับ Entity Framework (ฉันใช้ NHibernate เป็น ORM) แต่เมื่อฉันต้องทดสอบตรรกะของฐานข้อมูล ฉันจะใช้ sqlite กับฐานข้อมูลในหน่วยความจำ   -  person Claudio Redi    schedule 05.04.2014


คำตอบ (4)


อาจไม่ใช่สิ่งที่คุณต้องการได้ยิน แต่คุณไม่ต้องการล้อเลียน DbContext ฉันรู้ว่ามันทำมาโดยตลอด และใน EF6 มันง่ายยิ่งกว่าเดิมด้วยซ้ำ ยังมีอินเทอร์เฟซและวิธีการเสมือนเพิ่มเติมสำหรับการนำออบเจ็กต์จำลองไปใช้ ในทางเทคนิคแล้วมันก็ไม่ยาก

มันเป็นพฤติกรรมที่สำคัญ

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

ความแตกต่างระหว่างในหน่วยความจำและ LINQ ที่เชื่อมต่อนั้นล้นหลาม โดยส่วนตัวแล้ว ฉันทำการทดสอบการรวมสำหรับสิ่งใดก็ตามที่เกี่ยวข้องกับการสืบค้น LINQ to Entities เท่านั้น มันง่ายเกินไปที่จะสร้างกราฟวัตถุจำลองที่จะดูแตกต่างออกไปหาก EF สร้างขึ้น ในวิธีการบริการของฉัน บางครั้งฉันเขียนคำสั่งที่ค่อนข้างซับซ้อน อาจเกี่ยวข้องกับ Includes บางทีอาจจงใจละเว้น null guards โดยรู้ว่าคำสั่งนั้นถูกแปลเป็น SQL อาจเกี่ยวข้องกับการโหลดแบบ Lazy Loading หรืออาศัยการแก้ไขความสัมพันธ์ ฉันต้องตระหนักถึงสถานะของเอนทิตี อายุขัยของบริบท การตรวจสอบที่เกิดขึ้นเมื่อบันทึกการเปลี่ยนแปลง การทำงานพร้อมกัน ... ฉันแค่ไม่เชื่อการทดสอบสีเขียวเมื่อมันถูกเยาะเย้ยทั้งหมด

แน่นอนว่ายังมีตรรกะทางธุรกิจเหลืออยู่เพียงพอที่จะทดสอบด้วยการทดสอบหน่วยล้วนๆ เมื่อคุณสามารถสันนิษฐานได้ว่ามีออบเจ็กต์ที่ถูกต้อง (เนื่องจากคุณทดสอบแยกกันในการทดสอบการรวม) คุณสามารถเยาะเย้ยวัตถุเหล่านั้นและทดสอบหน่วยพฤติกรรมในหน่วยความจำได้

person Gert Arnold    schedule 05.04.2014

ในทางกลับกัน คุณจะได้ข้อมูลเพิ่มเติมอะไรจากการตั้งค่าฐานข้อมูลและทดสอบกับสิ่งนั้น

ฉันจะล้อเลียน DbContext เพราะมันจะง่ายที่สุดในการบำรุงรักษาและเนื่องจากไม่มีค่าในการทดสอบหน่วยการเรียกของ Entity-Framework กับฐานข้อมูล

สิ่งที่คุณต้องการทดสอบคือการสืบค้น LINQ ของคุณส่งคืนข้อมูลจากแหล่งข้อมูลหรือไม่ อย่างไรก็ตาม ข้อความค้นหา LINQ เหล่านั้นได้รับการแปลเป็นข้อความค้นหา SQL โดย EF ซึ่งเป็นสิ่งที่คุณไม่ต้องกังวล

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

person Jeroen Vannevel    schedule 05.04.2014

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

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

person J.W.    schedule 05.04.2014
comment
แม้ว่าตรรกะการทดสอบฐานข้อมูลอยู่นอกขอบเขตของการทดสอบหน่วยตามคำจำกัดความ แต่ในทางปฏิบัติ ผลลัพธ์ที่ได้ค่อนข้างสะดวกเมื่อพิจารณาว่าแบบสอบถามส่วนใหญ่มีตรรกะบางอย่างที่อาจมีจุดบกพร่อง ฉันใช้ sqllite เป็นการส่วนตัวสำหรับกรณีนี้ - person Claudio Redi; 05.04.2014
comment
ฉันเห็นด้วย แต่ฉันไม่แน่ใจว่า EF กับ sqlite ทำงานเหมือนกันกับ EF กับเซิร์ฟเวอร์ sql อาจให้ผลลัพธ์ที่แตกต่างออกไป - person J.W.; 05.04.2014

สิ่งที่ควรคำนึงถึงเมื่อเขียน Mock สำหรับ DBContext ของคุณและดำเนินการค้นหา LINQ ของคุณก็คือพวกเขากำลังทำงานกับวัตถุบริบทจำลองเป็น LINQ ไปยัง OBJECT ไม่ใช่ LINQ ไปยัง Entities... (EF6)...

โดยส่วนตัวแล้วฉันจะสละเวลาของคุณในการทดสอบพฤติกรรม Julie Lerman มีซีรี่ส์ @ pluralsight และ MSDN Mag ออนไลน์ที่ครอบคลุมวิธีทดสอบ dbContext หากคุณต้องการ

person Warren LaFrance    schedule 02.08.2014