Mocking vs Spying trong khuôn khổ chế giễu


131

Trong các khung mô phỏng , bạn có thể chế nhạo một đối tượng hoặc do thám nó. Sự khác biệt giữa hai và khi nào tôi nên / nên sử dụng cái này hơn cái kia?

Nhìn vào Mockito , ví dụ, tôi thấy những điều tương tự được thực hiện sử dụng gián điệpmocks , nhưng tôi không chắc chắn về sự khác biệt giữa hai người.



Câu trả lời:


156

Đối tượng giả thay thế hoàn toàn lớp giả, trả về các giá trị được ghi hoặc mặc định. Bạn có thể tạo ra giả từ "không khí mỏng". Đây là những gì chủ yếu được sử dụng trong quá trình thử nghiệm đơn vị.

Khi gián điệp, bạn lấy một đối tượng hiện có và chỉ "thay thế" một số phương thức. Điều này hữu ích khi bạn có một lớp lớn và chỉ muốn chế giễu một số phương thức nhất định (chế giễu một phần). Hãy để tôi trích dẫn tài liệu Mockito :

Bạn có thể tạo gián điệp của các đối tượng thực sự. Khi bạn sử dụng gián điệp thì các phương thức thực sự được gọi (trừ khi một phương thức được khai thác).

Các gián điệp thực sự nên được sử dụng cẩn thận và đôi khi , ví dụ như khi xử lý mã kế thừa.

Khi nghi ngờ, sử dụng giả.


1
Cảm ơn bạn! Điều đó làm cho nó rõ ràng hơn nhiều. Vì vậy, giả không bao giờ ủy thác cho đối tượng thực tế bị chế giễu bao giờ , nhưng gián điệp thì có.
Vivin Paliath

7
Giả không có "đối tượng thực tế" - giả được tạo ra ab initio.
Carl Manaster

4
Bất kỳ lời giải thích cho lý do tại sao Mockito cảnh báo chống lại việc sử dụng gián điệp mọi lúc? Tôi thấy rằng họ nói ủng hộ giả, nhưng tôi không rõ lý do tại sao.
Matt

8
Tôi không chắc, nhưng có lẽ vì họ là "Mockito" chứ không phải "Spyito": D
typoerrpr

16

Mockito cảnh báo rằng chế nhạo một phần không phải là một cách thực hành tốt và bạn nên xem lại kiến ​​trúc Hướng đối tượng của mình. Spy (hoặc chế nhạo một phần) được khuyến nghị để kiểm tra mã kế thừa .


16

Tôi sẽ cố gắng giải thích bằng một ví dụ ở đây:

// 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());
}

Ở đây, chúng tôi đã có đối tượng thực ban đầu list, trong đó chúng tôi đã thêm một yếu tố và kích thước dự kiến ​​là một.

Chúng tôi thám ý nghĩa đối tượng thực sự mà chúng tôi có thể hướng dẫn những phương pháp để được stubbed . Vì vậy, chúng tôi đã tuyên bố rằng chúng tôi vẫn còn phương pháp - size()trên đối tượng gián điệp sẽ trả về 10, bất kể kích thước thực tế là bao nhiêu.

Tóm lại, bạn sẽ theo dõi đối tượng thựckhai thác một số phương thức .


2

Tham khảo: http://javapointers.com/tutorial/difference-b between-spy-and-mock-in-mockito /

Khi sử dụng các đối tượng giả, hành vi mặc định của phương thức khi không còn sơ khai là không làm gì cả. Phương tiện đơn giản, nếu là phương thức void, thì nó sẽ không làm gì khi bạn gọi phương thức hoặc nếu phương thức đó có trả về thì nó có thể trả về null, rỗng hoặc giá trị mặc định.

Trong khi trong các đối tượng gián điệp, tất nhiên, vì nó là một phương thức thực sự, khi bạn không khai thác phương thức đó, thì nó sẽ gọi hành vi của phương thức thực. Nếu bạn muốn thay đổi và chế nhạo phương thức, thì bạn cần phải sơ khai nó.


2

Đối tượng giả được truyền xung quanh nhưng không bao giờ thực sự được sử dụng. Thông thường chúng chỉ được sử dụng để điền vào danh sách tham số.

Các đối tượng giả thực sự có các triển khai làm việc, nhưng thường sử dụng một số phím tắt khiến chúng không phù hợp để sản xuất (một cơ sở dữ liệu trong bộ nhớ là một ví dụ tốt).

Sơ khai cung cấp câu trả lời đóng hộp cho các cuộc gọi được thực hiện trong quá trình thử nghiệm, thường không phản hồi hoàn toàn cho bất kỳ điều gì bên ngoài những gì được lập trình trong thử nghiệm.

Các gián điệp là các cuống cũng ghi lại một số thông tin dựa trên cách chúng được gọi. Một dạng của điều này có thể là một dịch vụ email ghi lại số lượng tin nhắn được gửi.

Giả là những gì chúng ta đang nói ở đây: các đối tượng được lập trình sẵn với những kỳ vọng hình thành nên một đặc điểm kỹ thuật của các cuộc gọi mà chúng dự kiến ​​sẽ nhận được.

Mocks Ar't Stub của Martin Fowler


1

Điệp viên có hai định nghĩa. Một, là nơi mà phương thức thực được gọi, một phương thức khác, ở đó, không có chức năng nào được gọi và chỉ có các giá trị tương đương null hoặc null được trả về, nhưng các phương thức được gọi và trạng thái của chúng được ghi lại, thông thường, phương thức x được gọi là y lần.


0

Trong Mockito nếu bạn gán bất kỳ đối tượng nào cho biến đối tượng của Mock Object thì không ảnh hưởng đến Mock Object.

Nhưng trong trường hợp Spy, nếu bạn gán bất kỳ đối tượng nào cho biến đối tượng của Spy Object thì sẽ ảnh hưởng đến Spy Object vì Spy hoạt động giống như sửa đổi đối tượng thời gian thực.

Ví dụ tham khảo là

@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));
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.