ฉันอ่านบทความเมื่อเร็ว ๆ นี้ซึ่งกล่าวว่าวัตถุจำลองมักเข้าใจผิดและใช้ในทางที่ผิด มีรูปแบบการต่อต้านการเยาะเย้ยที่ชัดเจนซึ่งฉันสามารถระวังได้หรือไม่?
ฉันอ่านบทความเมื่อเร็ว ๆ นี้ซึ่งกล่าวว่าวัตถุจำลองมักเข้าใจผิดและใช้ในทางที่ผิด มีรูปแบบการต่อต้านการเยาะเย้ยที่ชัดเจนซึ่งฉันสามารถระวังได้หรือไม่?
คำตอบ:
ฉันเกลียดที่จะเห็นชั้นเรียนคอนกรีตที่เรียบง่ายล้อเลียนไป ตัวอย่างเช่นใช้คลาสแบบง่าย ๆ ดังต่อไปนี้ซึ่งไม่มีการพึ่งพาสิ่งอื่นใด:
public class Person
{
private readonly string _firstName;
private readonly string _surname;
public Person(string firstName, string surname)
{
if (String.IsNullOrEmpty(firstName))
{
throw new ArgumentException("Must have first name");
}
if (String.IsNullOrEmpty(surname))
{
throw new ArgumentException("Must have a surname");
}
_firstName = firstName;
_surname = surname;
}
public string Name
{
get
{
return _firstName + " " + _surname;
}
}
}
ในการทดสอบใด ๆ ที่เกี่ยวข้องกับคลาสนี้ฉันค่อนข้างจะเป็นของจริงที่ถูกสร้างอินสแตนซ์และใช้มากกว่าอินเทอร์เฟซบางอย่างเช่น 'IPerson' ที่ถูกดึงออกมา โดยการใช้จริงการทดสอบของคุณเป็นจริงมากขึ้น (คุณมีการตรวจสอบพารามิเตอร์ในสถานที่และการใช้งานจริงของคุณสมบัติ 'ชื่อ') สำหรับคลาสที่เรียบง่ายเช่นนี้คุณไม่ได้ทำการทดสอบช้าลงกำหนดตรรกะน้อยลงหรือทำให้ยุ่งเหยิงน้อยลง (คุณไม่จำเป็นต้องรู้ว่าชื่อนั้นถูกเรียกเมื่อทำการทดสอบคลาสอื่น ๆ ) - ซึ่งเป็นเหตุผลทั่วไปในการเยาะเย้ย / stubbing
ในฐานะที่เป็นส่วนขยายของสิ่งนี้ฉันได้เห็นผู้คนเขียนการทดสอบที่จำลองถูกตั้งค่าด้วยความคาดหวังจากนั้นจำลองนั้นจะถูกเรียกโดยตรงในการทดสอบ การทดสอบที่น่าประหลาดใจจะผ่าน ... hmmmm ...
มันอาจฟังดูชัดเจน แต่: อย่าใช้วัตถุจำลองในรหัสการผลิต! ฉันเคยเห็นตัวอย่างมากกว่าหนึ่งตัวอย่างซึ่งรหัสการผลิตขึ้นอยู่กับลักษณะของวัตถุจำลองบางอย่าง ( MockHttpServletRequest
จากตัวอย่างของ Springframework)
ในความคิดของฉันมันตรวจสอบการเรียกใช้วิธีมากเกินไปใน mocks ฉันรู้สึกว่านี่เป็นวิธีปฏิบัติที่บังคับใช้โดยกรอบการเยาะเย้ยไม่กี่อย่างเช่น EasyMock ซึ่งพฤติกรรมการเยาะเย้ยเริ่มต้นจะล้มเหลวเมื่อใดก็ตามที่มีการเรียกใช้เมธอดเพิ่มเติมที่ไม่ได้ระบุไว้อย่างชัดเจนมาก่อน การตรวจสอบวิธีการจำลองที่เข้มงวดชนิดนี้สามารถนำไปสู่การออกแบบที่เปราะซึ่งการเปลี่ยนแปลงที่น้อยที่สุดของรหัสสามารถนำไปสู่การทดสอบทั้งชุดที่ล้มเหลวแม้ว่าการทำงานหลักยังคงเหมือนเดิม
วิธีแก้ไขปัญหานี้เริ่มใช้สตับแทน mocks บทความที่ฉันพบว่าให้ความกระจ่างเกี่ยวกับเรื่องนี้เป็นเรื่องที่พบใน Javadoc ของ Mockito: http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html (ดู "2. การขัดถูบางอย่าง?" ) เชื่อมโยงไปยัง: http://monkeyisland.pl/2008/07/12/should-i-worry-about-the-unexpected/
ฉันสนุกกับการทำงานกับ Mockito จนถึงตอนนี้เพราะมันไม่ได้บังคับใช้พฤติกรรมการเยาะเย้ยที่เข้มงวดนี้ แต่เป็นการใช้สตับแทน นอกจากนี้ยังบังคับใช้การตรวจสอบวิธีการกับวัตถุเฉพาะแทนวัตถุจำลองทั้งหมด ดังนั้นคุณจะต้องตรวจสอบเฉพาะวิธีการที่สำคัญในสถานการณ์ทดสอบของคุณ
มีหนังสืออยู่สองสามเล่มที่นี่และฉันขอแนะนำให้แตะที่เรื่องนี้และเยาะเย้ยและเรื่องทั่วไป:
รูปแบบ xUnit
ศิลปะแห่งการทดสอบหน่วย: ด้วยตัวอย่างใน. Net
การทดสอบ Java ยุคใหม่: TestNG และแนวคิดขั้นสูง (หนังสือเล่มนี้ส่วนใหญ่เกี่ยวกับ testNG แต่มีบทที่ดีเกี่ยวกับการเยาะเย้ย)
Answer.RETURNS_SMART_NULLS
ตั้งค่าสำหรับ mocks ซึ่งช่วยวินิจฉัยปัญหานี้
ฉันสังเกตรูปแบบการต่อต้านเพียงเล็กน้อยในประสบการณ์ของฉัน
มิฉะนั้นประสบการณ์ของฉันกับ mocks โดยเฉพาะ Mockito เป็นเรื่องง่าย พวกเขาทำแบบทดสอบง่ายมากในการเขียนและบำรุงรักษา การทดสอบการโต้ตอบ / การเสนอมุมมองของ GWT นั้นทำได้ง่ายกว่าด้วย mocks มากกว่า GWTTestCase
ฉันพบว่าการทดสอบที่ใช้ mocks ในหลาย ๆ ชั้นของแอปพลิเคชันโดยเฉพาะอย่างยิ่งยากที่จะถอดรหัสและเปลี่ยนแปลง อย่างไรก็ตามฉันคิดว่าสิ่งนี้ได้รับการลดลงในช่วงไม่กี่ปีที่ผ่านมาด้วยการปรับปรุง API เฟรมเวิร์กของจำลอง
5 หรือ 6 ปีที่ผ่านมา API อย่าง EasyMock มีประสิทธิภาพ แต่ยุ่งยากมาก บ่อยครั้งที่รหัสทดสอบที่ใช้เป็นลำดับความสำคัญมีความซับซ้อนมากกว่ารหัสที่ใช้ในการทดสอบ ย้อนกลับไปตอนนั้นฉันพยายามโน้มน้าวทีมที่ฉันใช้อย่างไม่ จำกัด และทำด้วยมือ mocks แบบเรียบง่ายซึ่งเป็นเพียงการติดตั้งอินเตอร์เฟสใหม่สำหรับการทดสอบโดยเฉพาะ
เมื่อเร็ว ๆ นี้ความคิดเห็นที่แข็งแกร่งของฉันเกี่ยวกับเรื่องนี้อ่อนลงเนื่องจาก API การเยาะเย้ยทำให้การทดสอบที่ใช้พวกเขาอ่านง่ายขึ้น โดยพื้นฐานแล้วฉันต้องการให้โค้ดของฉัน (รวมถึงการทดสอบ) สามารถเปลี่ยนแปลงได้โดยผู้พัฒนารายอื่นโดยไม่ทำให้พวกเขารู้สึกว่าพวกเขากำลังเปลี่ยนผ่านการเรียก API ที่คลุมเครือ