การล้อเลียนกับการสอดแนมในกรอบการล้อเลียน


131

ในกรอบการเยาะเย้ยคุณสามารถล้อเลียนวัตถุหรือสอดแนมได้ อะไรคือความแตกต่างระหว่างทั้งสองและเมื่อใดที่ฉันจะ / ควรใช้อีกอันหนึ่ง?

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



อาจซ้ำกันได้ของstackoverflow.com/questions/28295625/mockito-spy-vs-mock
Abhinav

คำตอบ:


157

อ็อบเจ็กต์จำลองแทนที่คลาสที่เยาะเย้ยทั้งหมดโดยส่งคืนค่าที่บันทึกไว้หรือค่าเริ่มต้น คุณสามารถสร้างภาพจำลองจาก "อากาศเบาบาง" นี่คือสิ่งที่ส่วนใหญ่จะใช้ในระหว่างการทดสอบหน่วย

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

คุณสามารถสร้างสายลับของวัตถุจริง เมื่อคุณใช้สายลับจะมีการเรียกใช้วิธีการจริง (เว้นแต่ว่าวิธีการนั้นจะถูกขีดฆ่า)

ควรใช้สายลับตัวจริงอย่างระมัดระวังและเป็นครั้งคราวเช่นเมื่อต้องจัดการกับรหัสเดิม

หากมีข้อสงสัยให้ใช้ล้อเลียน


1
ขอบคุณ! นั่นทำให้ชัดเจนขึ้นมาก คนล้อเลียนจึงไม่เคยมอบหมายให้วัตถุจริงที่ถูกล้อเลียนเลยแต่สายลับทำ
Vivin Paliath

7
Mocks ไม่มี "วัตถุจริง" - การจำลองถูกสร้างขึ้นโดยเริ่มต้น
Carl Manaster

4
มีคำอธิบายว่าทำไม Mockito ถึงเตือนไม่ให้ใช้สายลับตลอดเวลา? ฉันเห็นว่าพวกเขาชอบล้อเลียน แต่ฉันไม่ชัดเจนในเหตุผลว่าทำไม
Matt

9
ฉันไม่แน่ใจ แต่อาจเป็นเพราะมันเป็น "Mockito" ไม่ใช่ "Spyito": D
typoerrpr

16

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


16

ฉันจะพยายามอธิบายโดยใช้ตัวอย่างที่นี่:

// Difference between mocking, stubbing and spying
@Test
public void differenceBetweenMockingSpyingAndStubbing() {
    List list = new ArrayList();
    list.add("abc");
    assertEquals(1, list.size());

    List mockedList = spy(list);
    when(mockedList.size()).thenReturn(10);
    assertEquals(10, mockedList.size());
}

ที่นี่เรามีวัตถุจริงเริ่มต้นlistซึ่งเราได้เพิ่มองค์ประกอบหนึ่งและขนาดที่คาดว่าจะเป็นหนึ่ง

เราสอดแนมความหมายที่แท้จริงของวัตถุที่เราสามารถแนะนำวิธีการที่จะค้างอยู่ ดังนั้นเราจึงประกาศว่าเราใช้วิธีการขีดฆ่า - size()บนวัตถุสอดแนมซึ่งจะส่งคืน 10 ไม่ว่าขนาดจริงจะเป็นเท่าใดก็ตาม

สรุปคุณจะสอดแนม วัตถุจริงและต้นขั้ว บางส่วนของวิธีการ


2

อ้างอิง: http://javapointers.com/tutorial/difference-between-spy-and-mock-in-mockito/

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

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


2

วัตถุจำลองถูกส่งไปรอบ ๆ แต่ไม่เคยใช้จริง โดยปกติจะใช้เพื่อเติมรายการพารามิเตอร์

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

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

สายลับคือต้นขั้วที่บันทึกข้อมูลบางอย่างตามวิธีการเรียก รูปแบบหนึ่งอาจเป็นบริการอีเมลที่บันทึกจำนวนข้อความที่ส่ง

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

Mocks ไม่ใช่ Stubs โดย Martin Fowler


1

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


0

ใน Mockito หากคุณกำหนดอ็อบเจกต์ใด ๆ ให้กับตัวแปรอินสแตนซ์ของ Mock Object จะไม่มีผลกับ Mock Object

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

สำหรับตัวอย่างการอ้างอิงคือ

@RunWith(MockitoJUnitRunner.class)
public class MockSpyExampleTest {

    @Mock
    private List<String> mockList;

    @Spy
    private List<String> spyList = new ArrayList();

    @Test
    public void testMockList() {
        //by default, calling the methods of mock object will do nothing
        mockList.add("test");
        assertNull(mockList.get(0));
    }

    @Test
    public void testSpyList() {
        //spy object will call the real method when not stub
        spyList.add("test");
        assertEquals("test", spyList.get(0));
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.