ความแตกต่างระหว่างการแกล้งเยาะเย้ยและการขัดถูคืออะไร


706

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

นี่คือวิธีที่ฉันใช้

ปลอม : คลาสที่ใช้อินเทอร์เฟซ แต่มีข้อมูลคงที่และไม่มีตรรกะ เพียงส่งคืนข้อมูล "ดี" หรือ "ไม่ดี" ขึ้นอยู่กับการใช้งาน

เยาะเย้ย : ชั้นเรียนที่ใช้อินเตอร์เฟซและช่วยให้ความสามารถในการตั้งค่าแบบไดนามิกเพื่อส่งกลับ / ข้อยกเว้นที่จะโยนจากวิธีการเฉพาะและให้ความสามารถในการตรวจสอบว่าวิธีการเฉพาะได้รับการเรียก / ไม่เรียก

Stub : เช่นเดียวกับคลาส mock ยกเว้นว่ามันไม่ได้ให้ความสามารถในการตรวจสอบว่าวิธีการที่ได้รับการเรียก / ไม่ได้เรียกว่า

mocks และ stubs สามารถสร้างขึ้นด้วยมือหรือสร้างขึ้นโดยกรอบการเยาะเย้ย ชั้นเรียนปลอมถูกสร้างขึ้นด้วยมือ ฉันใช้ mocks เป็นหลักในการตรวจสอบการมีปฏิสัมพันธ์ระหว่างชั้นเรียนของฉันและชั้นเรียนที่ขึ้นต่อกัน ฉันใช้สตับเมื่อฉันตรวจสอบการมีปฏิสัมพันธ์และกำลังทดสอบเส้นทางอื่นผ่านโค้ดของฉัน ฉันใช้คลาสปลอมเป็นหลักในการสรุปข้อมูลการพึ่งพาข้อมูลหรือเมื่อ mocks / stubs น่าเบื่อเกินกว่าที่จะตั้งค่าในแต่ละครั้ง


6
โดยทั่วไปคุณบอกว่ามันทั้งหมดใน "คำถาม" ของคุณ :) ฉันคิดว่าคำเหล่านั้นเป็นคำตอบที่ยอมรับได้ดีในคำศัพท์เหล่านั้น
Eran Galperin

2
คำจำกัดความของวิกิพีเดียของปลอมแตกต่างจากนี้ยืนยันว่าปลอม "ใช้เป็นการดำเนินงานที่ง่ายขึ้นเช่นการใช้ฐานข้อมูลในหน่วยความจำในการทดสอบแทนที่จะทำการเข้าถึงฐานข้อมูลจริง" ดูen.wikipedia.org/wiki/Test_double
zumalifeguard

2
ฉันได้เรียนรู้จากทรัพยากรต่อไปนี้มีคำอธิบายที่ดีเยี่ยมโดยโรเบิร์ตซีมาร์ติน (ลุงบ๊อบ): The Little เยาะเย้ยในบล็อกรหัสสะอาด มันอธิบายความแตกต่างระหว่างและรายละเอียดปลีกย่อยของหุ่นทดสอบคู่, stubs, สายลับ, mocks (จริง) และปลอม นอกจากนี้ยังกล่าวถึง Martin Fowler และอธิบายประวัติการทดสอบซอฟต์แวร์สักหน่อย
Erik

test.googleblog.com/2013/07/… (สรุปหน้าเดียวสั้น ๆ )
ShreevatsaR

นี่คือเวลาของฉันที่จะอธิบายว่า: Test Doubles: Fakes, Stubs และ Mocks (โพสต์บล็อกพร้อมตัวอย่าง)
michal-lipski

คำตอบ:


549

คุณสามารถรับข้อมูลบางอย่าง:

จากMartin Fowler เกี่ยวกับ Mock and Stub

วัตถุปลอมมีการใช้งานจริง แต่โดยปกติจะใช้ทางลัดบางอย่างซึ่งทำให้พวกเขาไม่เหมาะสำหรับการผลิต

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

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

จากxunitpattern :

ปลอม : เราได้รับหรือสร้างการใช้งานที่มีน้ำหนักเบามากของฟังก์ชั่นเดียวกับที่ให้ไว้โดยส่วนประกอบที่ SUT ขึ้นอยู่กับและแนะนำให้ SUT ใช้แทนของจริง

Stub : การใช้งานนี้ได้รับการกำหนดค่าให้ตอบสนองต่อการโทรจาก SUT ด้วยค่า (หรือข้อยกเว้น) ที่จะใช้รหัสที่ไม่ได้ทดสอบ (ดูข้อบกพร่องการผลิตในหน้า X) ภายใน SUT ข้อบ่งชี้สำคัญสำหรับการใช้ Test Stub คือรหัสที่ยังไม่ผ่านการทดสอบซึ่งเกิดจากการไม่สามารถควบคุมอินพุตทางอ้อมของ SUT

จำลองวัตถุที่ใช้อินเทอร์เฟซเดียวกันเป็นวัตถุที่ SUT (ระบบภายใต้การทดสอบ) ขึ้นอยู่กับ เราสามารถใช้ Mock Object เป็นจุดสังเกตเมื่อเราจำเป็นต้องทำการตรวจสอบพฤติกรรมเพื่อหลีกเลี่ยงความต้องการที่ยังไม่ทดลอง (ดูข้อบกพร่องการผลิตในหน้า X) ที่เกิดจากการไม่สามารถสังเกตผลข้างเคียงของวิธีการเรียกใช้บน SUT

ส่วนตัว

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


9
ดูเหมือนว่าสำหรับฉันคำจำกัดความของ Stub และ Fake จะกลับรายการในคำพูด xUnitPattern เทียบกับคำพูดของ Martin Fowler นอกจากนี้คำจำกัดความของมาร์ตินฟาวเลอร์เรื่อง Stub and Fake นั้นตรงกันข้ามกับคำจำกัดความในคำถามดั้งเดิมของ tvanfosson ในความเป็นจริงมีคำจำกัดความที่ยอมรับกันโดยทั่วไปของคำสองคำนี้หรือไม่นั้นขึ้นอยู่กับว่าคุณกำลังพูดถึงใคร
Simon Tewsi

3
+1 สำหรับ "ฉันพยายามทำให้ง่ายขึ้นโดยใช้: จำลองและต้นขั้ว" เป็นความคิดที่ดีมาก!
Brad Cupit

4
ไม่เห็นว่าการใช้เฉพาะ Mock และ Stub เป็นความคิดที่ดีเพียงใด การทดสอบทุกคู่มีจุดประสงค์และการใช้งาน
Hector Ordonez

1
ฉันไม่เห็นความแตกต่างระหว่าง Fake และ Mock ในคำจำกัดความของ MF
IdontCareAboutReputationPoints

2
@MusuNaji: ในคำจำกัดความของ MF ไม่มี "ความคาดหวัง" ที่เกี่ยวกับบทสนทนาของปลอมนอกจากจะมีการใช้อินเทอร์เฟซ ในทางกลับกันเยาะเย้ยจะถูกท้าทาย (วิธีนี้เรียกว่า?)
dbalakirev

205

Stub - วัตถุที่ให้คำตอบที่กำหนดไว้ล่วงหน้าสำหรับการเรียกใช้เมธอด

เยาะเย้ย - วัตถุที่คุณตั้งความคาดหวัง

ปลอม - วัตถุที่มีความสามารถ จำกัด (เพื่อวัตถุประสงค์ในการทดสอบ) เช่นบริการเว็บปลอม

Test Double เป็นคำทั่วไปสำหรับ stubs mocks และ fakes แต่อย่างไม่เป็นทางการคุณมักจะได้ยินเสียงคนเรียกง่ายๆว่าล้อเลียน


4
ใครช่วยอธิบาย & ให้คำตอบฉันว่า "คำตอบสำเร็จรูป" ในบริบทนี้คืออะไร
MasterMastic

14
ค่าที่ชัดเจนมากกว่าค่าที่คำนวณ
Mike

ที่สุด! คำจำกัดความบางอย่างที่ฉันเข้าใจ! จากคำจำกัดความเหล่านี้แล้วgoogletest (gtest) / googlemock (gmock)อนุญาตให้วัตถุที่เยาะเย้ยเป็น stubs ด้วยเช่นกันเนื่องจากคุณสามารถสร้างEXPECT_CALL()s บนวิธีการที่เยาะเย้ยซึ่งบังคับเอาท์พุทบางอย่างตามอินพุตที่แน่นอนโดยใช้ชนิด.WillOnce(Invoke(my_func_or_lambda_func))(หรือพร้อม.WillRepeatedly()) EXPECT_CALL()ไวยากรณ์ที่แนบมากับ ตัวอย่างบางส่วนของการใช้Invoke()สามารถเห็นได้ในบริบทที่แตกต่างที่ด้านล่างของคำตอบยาวของฉันที่นี่: stackoverflow.com/a/60905880/4561887
Gabriel Staples

เอกสาร Gmock บนInvoke()อยู่ที่นี่: github.com/google/googletest/blob/master/googlemock/docs/... อย่างไรก็ตามข้อสรุปคือ: Google เยาะเย้ย (gmock) ช่วยให้หนึ่งสามารถสร้างทั้ง mocks และต้นขั้วได้อย่างง่ายดายแม้ว่า mocks ส่วนใหญ่ไม่ได้เป็นต้นขั้ว
Gabriel Staples

Mocks เป็นซูเปอร์เซ็ตของ Stubs พวกเขายังสามารถตอบกลับคำตอบที่กำหนดไว้ล่วงหน้า แต่ยังอนุญาตให้นักพัฒนาตั้งความคาดหวัง IMO ห้องสมุดบางแห่งออกนอกลู่นอกทางเส้นของหุ่นทดสอบทั้งหมด
ลุค

94

ฉันกำลังประหลาดใจว่าคำถามนี้ได้รับรอบเป็นเวลานานและไม่มีใครได้ให้ยังเป็นคำตอบขึ้นอยู่กับรอย Osherove ของ "ศิลปะของหน่วยทดสอบ"

ใน "3.1 แนะนำต้นขั้ว" กำหนดต้นขั้วเป็น:

Stub เป็นการแทนที่ที่สามารถควบคุมได้สำหรับการพึ่งพา (หรือผู้ทำงานร่วมกัน) ที่มีอยู่ในระบบ โดยการใช้ stub คุณสามารถทดสอบโค้ดของคุณโดยไม่เกี่ยวข้องกับการพึ่งพาโดยตรง

และกำหนดความแตกต่างระหว่างต้นขั้วและ mocks เป็น:

สิ่งสำคัญที่ต้องจำเกี่ยวกับ mocks กับ stubs ก็คือ mocks นั้นก็เหมือนต้นขั้ว แต่คุณยืนยันกับวัตถุจำลองในขณะที่คุณไม่ได้ยืนยันกับต้นขั้ว

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

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

  • เมื่อการทดสอบของคุณตรวจสอบค่าในชั้นเรียนภายใต้การทดสอบหรือจริงทุกที่ยกเว้นของปลอมมีการใช้ของปลอมเป็นต้นขั้ว มันให้ค่าสำหรับคลาสที่อยู่ภายใต้การทดสอบเพื่อใช้โดยตรงผ่านค่าที่ส่งคืนโดยการเรียกใช้หรือโดยทางอ้อมผ่านการทำให้เกิดผลข้างเคียง (ในบางสถานะ) อันเป็นผลมาจากการเรียกใช้
  • เมื่อการทดสอบของคุณตรวจสอบค่าของปลอมมันถูกใช้เป็นจำลอง

ตัวอย่างของการทดสอบที่ใช้คลาส FakeX เป็น stub:

const pleaseReturn5 = 5;
var fake = new FakeX(pleaseReturn5);
var cut = new ClassUnderTest(fake);

cut.SquareIt;

Assert.AreEqual(25, cut.SomeProperty);

fakeเช่นใช้เป็นต้นขั้วเพราะที่Assertไม่ได้ใช้fakeในทุก

ตัวอย่างของการทดสอบที่การทดสอบคลาส X ถูกใช้เป็นจำลอง:

const pleaseReturn5 = 5;
var fake = new FakeX(pleaseReturn5);
var cut = new ClassUnderTest(fake);

cut.SquareIt;

Assert.AreEqual(25, fake.SomeProperty);

ในกรณีนี้การAssertตรวจสอบค่าเปิดfakeทำให้ปลอมจำลอง

ตอนนี้แน่นอนตัวอย่างเหล่านี้มีการวางแผนอย่างสูง แต่ฉันเห็นข้อดีอันยิ่งใหญ่ในความแตกต่างนี้ มันทำให้คุณรู้ว่าคุณกำลังทดสอบสิ่งของของคุณอย่างไรและการอ้างอิงของการทดสอบของคุณอยู่ที่ไหน

ฉันเห็นด้วยกับ Osherove

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

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

ฉันตระหนักดีว่าการเขียนข้อความยืนยันกับของปลอมเป็นเรื่องธรรมดาโดยเฉพาะอย่างยิ่งเมื่อคุณเป็นสมาชิกประเภท TDD ที่ชอบเยาะเย้ย ฉันเดาว่าฉันแน่นแฟ้นกับ Martin Fowler ในค่าย classicist (ดู"Mocks ไม่ใช่ Stubs" ของ Martin Fowler ) และเหมือนกับ Osherove หลีกเลี่ยงการทดสอบการมีปฏิสัมพันธ์

เพื่อความสนุกสนานในการอ่านเกี่ยวกับสาเหตุที่คุณควรหลีกเลี่ยง mocks ตามที่กำหนดไว้ที่นี่ google สำหรับ "fowler mockist classicist" คุณจะได้พบกับความคิดเห็นมากมาย


31

ดังที่ได้กล่าวไว้ในคำตอบที่ได้รับการโหวตมาร์ตินฟาวเลอร์กล่าวถึงความแตกต่างเหล่านี้ในMocks Ar ไม่ใช่ Stubsและโดยเฉพาะอย่างยิ่งหัวข้อย่อยThe Difference ระหว่าง Mocks และ Stubsดังนั้นโปรดอ่านบทความนั้น

แทนที่จะมุ่งเน้นไปที่วิธีการที่สิ่งเหล่านี้จะแตกต่างกันผมคิดว่ามันมากขึ้น enlightening ที่จะมุ่งเน้นว่าทำไมเหล่านี้เป็นแนวความคิดที่แตกต่างกัน แต่ละคนมีอยู่เพื่อจุดประสงค์ที่แตกต่างกัน

ปลอม

ปลอมคือการดำเนินการที่จะทำงาน "ธรรมชาติ" แต่ไม่ได้เป็น "ของจริง" เหล่านี้เป็นแนวคิดที่คลุมเครือและผู้คนต่างมีความเข้าใจที่แตกต่างกันในสิ่งที่ทำให้สิ่งต่าง ๆ เป็นของปลอม

ตัวอย่างหนึ่งของปลอมคือฐานข้อมูลในหน่วยความจำ (เช่นใช้ sqlite กับ:memory:ร้านค้า) คุณจะไม่ใช้สิ่งนี้เพื่อการผลิต (เนื่องจากไม่มีการยืนยันข้อมูล) แต่มันก็เพียงพอแล้วที่จะใช้เป็นฐานข้อมูลเพื่อใช้ในสภาพแวดล้อมการทดสอบ นอกจากนี้ยังมีน้ำหนักเบากว่าฐานข้อมูล "ของจริง" มาก

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

เป็นตัวอย่างที่สามลองนึกภาพวัตถุที่มีแคช API วัตถุที่ใช้อินเทอร์เฟซที่ถูกต้อง แต่ก็ไม่มีการแคชเลย แต่ส่งคืนแคชที่พลาดเสมอจะเป็นของปลอม

จุดประสงค์ของปลอมไม่ได้ส่งผลกระทบต่อพฤติกรรมของระบบภายใต้การทดสอบแต่เพื่อลดความยุ่งยากในการใช้งานการทดสอบ (โดยการลบการอ้างอิงที่ไม่จำเป็น

ไม่สมบูรณ์

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

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

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

mocks

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

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

Mocks เชื่อมโยงกับการทดสอบการโต้ตอบซึ่งเป็นวิธีการทดสอบที่เฉพาะเจาะจง ผู้ที่ต้องการทดสอบสถานะของระบบมากกว่าการโต้ตอบของระบบจะใช้ mocks เท่าที่จำเป็น

ทดสอบสองเท่า

ปลอมไม่สมบูรณ์และ mocks ทั้งหมดอยู่ในหมวดหมู่ของคู่ทดสอบ การทดสอบสองครั้งเป็นวัตถุหรือระบบใด ๆ ที่คุณใช้ในการทดสอบแทนที่จะเป็นอย่างอื่น การทดสอบซอฟต์แวร์อัตโนมัติส่วนใหญ่เกี่ยวข้องกับการใช้การทดสอบสองเท่าหรืออย่างอื่น บางชนิดอื่น ๆ ของคู่ทดสอบรวมถึงค่าหุ่น , สายลับ , และ I / O blackholes


11

แสดงให้เห็นถึงการใช้งานของตับและ mocks ที่ฉันอยากจะ ได้แก่ ตัวอย่างขึ้นอยู่กับรอย Osherove ของ " ศิลปะของหน่วยทดสอบ "

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

นี่คือตรรกะที่เราต้องการทดสอบภายใน LogAnalyzer:

if(fileName.Length<8)
{
 try
  {
    service.LogError("Filename too short:" + fileName);
  }
 catch (Exception e)
  {
    email.SendEmail("a","subject",e.Message);
  }
}

คุณทดสอบอย่างไรว่า LogAnalyzer เรียกบริการอีเมลอย่างถูกต้องเมื่อบริการเว็บส่งข้อยกเว้น? นี่คือคำถามที่เราเผชิญ:

  • เราจะเปลี่ยนบริการเว็บได้อย่างไร

  • เราจะจำลองข้อยกเว้นจากบริการบนเว็บเพื่อทดสอบการโทรไปยังบริการอีเมลได้อย่างไร

  • เราจะรู้ได้อย่างไรว่าบริการอีเมลนั้นถูกเรียกอย่างถูกต้องหรือไม่?

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

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

[TestFixture]
public class LogAnalyzer2Tests
{
[Test]
 public void Analyze_WebServiceThrows_SendsEmail()
 {
   StubService stubService = new StubService();
   stubService.ToThrow= new Exception("fake exception");
   MockEmailService mockEmail = new MockEmailService();

   LogAnalyzer2 log = new LogAnalyzer2();
   log.Service = stubService
   log.Email=mockEmail;
   string tooShortFileName="abc.ext";
   log.Analyze(tooShortFileName);

   Assert.AreEqual("a",mockEmail.To); //MOCKING USED
   Assert.AreEqual("fake exception",mockEmail.Body); //MOCKING USED
   Assert.AreEqual("subject",mockEmail.Subject);
 }
}

9

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


1
ในขณะที่คำตอบอื่น ๆ มีรายละเอียดที่ดีและดีจริงๆ อันนี้ทำให้ชัดเจนและง่ายต่อการสร้างความแตกต่างมันยากที่จะไม่ลงคะแนน GJ!
Mario Garcia

6

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


6

หากคุณคุ้นเคยกับ Arrange-Act-Assert แล้ววิธีหนึ่งในการอธิบายความแตกต่างระหว่างต้นขั้วและจำลองที่อาจเป็นประโยชน์สำหรับคุณก็คือต้นขั้วนั้นอยู่ในส่วนของการจัดเรียงเนื่องจากเป็นการจัดเรียงสถานะอินพุตและ mocks เป็นของ ส่วนการยืนยันตามที่ใช้สำหรับการยืนยันผลลัพธ์

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


3

Stub, Fakes และ Mocks มีความหมายแตกต่างกันไปตามแหล่งต่าง ๆ ฉันแนะนำให้คุณแนะนำคำภายในทีมของคุณและยอมรับความหมายของพวกเขา

ฉันคิดว่ามันสำคัญที่จะต้องแยกความแตกต่างระหว่างสองวิธี: - การตรวจสอบพฤติกรรม (หมายถึงการทดแทนพฤติกรรม) - การตรวจสอบความถูกต้องของสถานะปลายทาง (หมายถึงการจำลองพฤติกรรม)

พิจารณาการส่งอีเมลในกรณีที่เกิดข้อผิดพลาด เมื่อทำการตรวจสอบพฤติกรรม - คุณตรวจสอบวิธีการที่SendการIEmailSenderดำเนินการครั้งเดียว และคุณต้องจำลองผลลัพธ์การส่งคืนของวิธีนี้ส่งคืนรหัสของข้อความที่ส่ง ดังนั้นคุณกล่าวว่า"ผมคาดหวังว่าSendจะได้รับการเรียกและฉันก็จะกลับมาหุ่น (หรือสุ่ม) รหัสสำหรับการโทรใด ๆ ." นี่คือการตรวจสอบพฤติกรรม: emailSender.Expect(es=>es.Send(anyThing)).Return((subject,body) => "dummyId")

เมื่อทำการตรวจสอบรัฐคุณจะต้องสร้างการดำเนินการที่TestEmailSender IEmailSenderและใช้Sendวิธีการ - โดยการบันทึกอินพุตลงในโครงสร้างข้อมูลบางอย่างที่จะใช้สำหรับการตรวจสอบสถานะในอนาคตเช่นอาร์เรย์ของวัตถุบางอย่างSentEmailsจากนั้นจะทดสอบว่าคุณจะตรวจสอบว่าSentEmailsมีอีเมลที่คาดหวังหรือไม่ นี่คือการตรวจสอบสถานะ: Assert.AreEqual(1, emailSender.SentEmails.Count)

จากการอ่านของฉันฉันเข้าใจว่าการตรวจสอบพฤติกรรมมักจะเรียกว่าMocks และการตรวจสอบของรัฐมักจะเรียกว่ากุดหรือปลอม


รายละเอียดที่ดีและคมชัดดีจริงๆ
shyam sundar singh tomar

2

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

public class MyUnitTest {

 @Test
 public void testConcatenate() {
  StubDependency stubDependency = new StubDependency();
  int result = stubDependency.toNumber("one", "two");
  assertEquals("onetwo", result);
 }
}

public class StubDependency() {
 public int toNumber(string param) {
  if (param == “one”) {
   return 1;
  }
  if (param == “two”) {
   return 2;
  }
 }
}

การเยาะเย้ยเป็นขั้นตอนขึ้นมาจากของปลอมและต้นขั้ว Mocks จัดเตรียมการทำงานเช่นเดียวกับสตับ แต่มีความซับซ้อนมากกว่า พวกเขาสามารถมีกฎที่กำหนดไว้สำหรับพวกเขาที่กำหนดในสิ่งที่วิธีการสั่งซื้อบน API ของพวกเขาจะต้องเรียกว่า mocks ส่วนใหญ่สามารถติดตามจำนวนครั้งที่มีการเรียกใช้วิธีการและสามารถตอบสนองตามข้อมูลนั้น โดยทั่วไปแล้ว mocks รู้บริบทของการโทรแต่ละครั้งและสามารถตอบสนองแตกต่างกันในสถานการณ์ที่แตกต่างกัน ด้วยเหตุนี้ mocks ต้องการความรู้บางอย่างของชั้นเรียนที่พวกเขากำลังเยาะเย้ย โดยทั่วไปแล้วต้นขั้วไม่สามารถติดตามจำนวนครั้งที่มีการเรียกใช้เมธอดหรือลำดับของเมธอดที่ถูกเรียก จำลองดูเหมือนว่า:

public class MockADependency {

 private int ShouldCallTwice;
 private boolean ShouldCallAtEnd;
 private boolean ShouldCallFirst;

 public int StringToInteger(String s) {
  if (s == "abc") {
   return 1;
  }
  if (s == "xyz") {
   return 2;
  }
  return 0;
 }

 public void ShouldCallFirst() {
  if ((ShouldCallTwice > 0) || ShouldCallAtEnd)
   throw new AssertionException("ShouldCallFirst not first thod called");
  ShouldCallFirst = true;
 }

 public int ShouldCallTwice(string s) {
  if (!ShouldCallFirst)
   throw new AssertionException("ShouldCallTwice called before ShouldCallFirst");
  if (ShouldCallAtEnd)
   throw new AssertionException("ShouldCallTwice called after ShouldCallAtEnd");
  if (ShouldCallTwice >= 2)
   throw new AssertionException("ShouldCallTwice called more than twice");
  ShouldCallTwice++;
  return StringToInteger(s);
 }

 public void ShouldCallAtEnd() {
  if (!ShouldCallFirst)
   throw new AssertionException("ShouldCallAtEnd called before ShouldCallFirst");
  if (ShouldCallTwice != 2) throw new AssertionException("ShouldCallTwice not called twice");
  ShouldCallAtEnd = true;
 }

}

1

fake objectเป็นการใช้งานจริงของอินเตอร์เฟส (โปรโตคอล) หรือการขยายการใช้การสืบทอดหรือวิธีการอื่น ๆ ที่สามารถใช้ในการสร้าง - คือการพึ่งพา โดยปกติแล้วมันจะถูกสร้างขึ้นโดยนักพัฒนาเป็นวิธีที่ง่ายที่สุดเพื่อทดแทนการพึ่งพาบางอย่าง

stub objectเป็นวัตถุเปล่า (0, ศูนย์และวิธีการที่ไม่มีตรรกะ) กับและพิเศษและรัฐ (โดยนักพัฒนา) ที่กำหนดไว้ล่วงหน้าเพื่อกำหนดค่าที่ส่งคืน มักจะถูกสร้างขึ้นโดยกรอบ

mock objectมีลักษณะคล้ายกันมากstub objectแต่มีการเปลี่ยนแปลงสถานะพิเศษระหว่างการทำงานของโปรแกรมเพื่อตรวจสอบว่ามีบางสิ่งเกิดขึ้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.