จะใช้ ArgumentCaptor เพื่อทำการขัดได้อย่างไร?


161

ในเอกสาร Mockito และjavadocsนั้นระบุไว้

ขอแนะนำให้ใช้ ArgumentCaptor กับการตรวจสอบ แต่ไม่ใช่ด้วยการขัด

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


1
คำอธิบายสั้น ๆ น่ารัก ๆ สั้น ๆ ที่นี่: dzone.com/articles/…
Benj

คำตอบ:


271

สมมติว่าวิธีการต่อไปนี้เพื่อทดสอบ:

public boolean doSomething(SomeClass arg);

เอกสาร Mockito บอกว่าคุณไม่ควรใช้ captor ด้วยวิธีนี้:

when(someObject.doSomething(argumentCaptor.capture())).thenReturn(true);
assertThat(argumentCaptor.getValue(), equalTo(expected));

เนื่องจากคุณสามารถใช้ตัวจับคู่ระหว่างการขัดถู:

when(someObject.doSomething(eq(expected))).thenReturn(true);

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

ArgumentCaptor<SomeClass> argumentCaptor = ArgumentCaptor.forClass(SomeClass.class);
verify(someObject).doSomething(argumentCaptor.capture());
assertThat(argumentCaptor.getValue(), equalTo(expected));

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

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

ไม่ฉันนับบล็อกพื้นหลังสีเทาทั้งหมดเป็นบล็อคโค้ด รวมถึงซับแรก ฉันอ้างถึงบรรทัดเมื่อ (someObject.doSomething (argumentCaptor.capture ()))) จากนั้นกลับมา (จริง);
ไม่สามารถบอก

ขอโทษด้วย ใช่ในกรณีนี้จริงจะถูกส่งคืนเสมอ
Rorick

3
ไม่แน่ใจว่าเหตุผลในการ "ไม่ใช้กับการขัดถู" เป็นเหตุผลง่ายๆ ผู้จับคู่ไม่ได้ให้ข้อโต้แย้งตามที่เราคาดหวังจริง (แค่เป็นประเภท) และนำไปสู่การมีการทดสอบที่ผ่านแม้ว่าข้อโต้แย้งที่อาจผิด
dtc

0

เส้น

when(someObject.doSomething(argumentCaptor.capture())).thenReturn(true);

จะทำเช่นเดียวกัน

when(someObject.doSomething(Matchers.any())).thenReturn(true);

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

และปัญหาอื่น: ถ้าใช้ argumentCaptor.capture () เมื่อทำการขัดมันจะไม่ชัดเจนว่าคุณควรคาดหวังค่าจำนวนเท่าใดหลังจากการตรวจสอบ เราต้องการเก็บค่าในระหว่างการตรวจสอบไม่ใช่ในระหว่างการขัดเพราะ ณ จุดนั้นยังไม่มีค่าที่จะจับ ดังนั้นตัวจับการโต้แย้งจับวิธีการจับภาพในระหว่างการทำอะไร? หรือไม่จับอะไรเลย? ฉันไม่มีคำตอบสำหรับคำถามนี้ ฉันคิดว่ามันเป็นพฤติกรรมที่ไม่ได้กำหนดและฉันไม่ต้องการใช้พฤติกรรมที่ไม่ได้กำหนด


0

สมมุติฐานถ้าการค้นหาทำให้คุณมีคำถามนี้คุณอาจต้องการสิ่งนี้:

doReturn(someReturn).when(someObject).doSomething(argThat(argument -> argument.getName().equals("Bob")));

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

และ 99% ของการทดสอบแตกต่างจาก null ที่คืนมาจาก Mock และในการออกแบบที่สมเหตุสมผลคุณจะหลีกเลี่ยงการส่งคืนnullค่าใช้จ่ายทั้งหมดOptionalหรือย้ายไปที่ Kotlin นี่หมายความว่าverifyไม่จำเป็นต้องใช้บ่อยและ ArgumentCaptors ก็น่าเบื่อเกินกว่าจะเขียน

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