Tags:

Sự khác nhau giữa Mock và Spy trong Mockito

Spy và Mock trong Mockito đều được dùng để tạo ra các mock object và giả lập kết quả trả về. Tuy nhiên, rất nhiều người lại thường nhầm lẫn 2 khái niệm này và thường xem nó như một.

Điểm khác nhau lớn nhất giữa Spy và Mock đó chính là đối với Mock chúng ta có thể tạo ra một mock object được giả lập hoàn toàn. Còn với Spy thì chúng ta có một object thật nhưng chúng ta vẫn có thể giả lập các kết quả trả về của chúng.

Mock object

Mock object được tạo ra trong Mockito thông qua @Mock annotation hoặc tạo thủ công bằng cách sử dụng method Mockito.mock(). Đây là một object giả thật sự và nó sẽ không làm gì ngay cả khi chúng ta không giả lập kết quả trả về.

Ví dụ nếu chúng ta gọi đến một void method của mock object nó sẽ chẳng làm gì đồng nghĩa với việc không có bất kỳ dòng code nào trong method này được thực thi. Hoặc nếu chúng ta gọi đến một method có trả về kết quả mà không giả lập kết quả trước đó thì kết quả trả về có thể là NULL hoặc EMPTY.

@ExtendWith(MockitoExtension.class)
public class MockExample {
    @Mock
    private List<String> mockList;

    @Test
    public void testMockList() {
        mockList.add("test");
        assertNull(mockList.get(0));
    }

    @Test
    public void testMockWithStub() {
        String expected = "Mock 100";
        when(mockList.get(100)).thenReturn(expected);

        assertEquals(expected, mockList.get(100));
    }
}

Trong ví dụ trên chúng ta có thể thấy, việc chúng ta gọi method add() của mock object hoàn toàn không có ý nghĩa và không có gì được thực thi tại đây.

Spy object

Spy object được tạo ra trong Mockito thông qua @Spy annotation hoặc tạo thủ công bằng cách sử dụng method Mockito.spy(). Đây là một object thật và khi chúng ta không giả lập kết quả trả về thì method đó sẽ được thực thi thật sự, ngược lại thì method này sẽ không được thực thi mà trả về kết quả như chúng ta mong đợi.

@ExtendWith(MockitoExtension.class)
public class SpyExample {

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


    @Test
    public void testSpyList() {
        spyList.add("test");
        assertEquals("test", spyList.get(0));
    }

    @Test
    public void testSpyWithStub() {
        String expected = "Spy 100";
        Mockito.doReturn(expected).when(spyList).get(100);

        assertEquals(expected, spyList.get(100));
    }
}

Chúng ta có thể thấy hàm testSpyList() đã không giả lập kết quả trả về cho Spy object vì vậy method thật sẽ được gọi và thực thi. Nhưng đối với testSpyWithStub() đã được giả lập kết quả trả về thì method thật sẽ không chạy mà trả về kết quả như chúng ta đã thiết lập trước đó.

Tóm lược

Qua bài viết này hy vọng các bạn sẽ phân biệt được 2 khái niệm này trong mockito.

Các bạn có thể tham khảo mã nguồn đầy đủ tại: mock-spy

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x