Mockito 中的 Spy

JavaJavaBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

介绍

Mockito 是一个用于 模拟单元测试 Java 应用程序的框架。在本实验中,我们将学习 Mockito 中的 Spy。Spy 类似于部分模拟对象,它会像模拟对象一样跟踪与对象的交互。此外,它还允许我们调用对象的所有正常方法。我们将使用 Mockito.spy() 方法和注解来创建 Spy,并演示如何对 Spy 进行存根操作。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("`Java`")) -.-> java/DataStructuresGroup(["`Data Structures`"]) java(("`Java`")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["`Object-Oriented and Advanced Concepts`"]) java/DataStructuresGroup -.-> java/collections_methods("`Collections Methods`") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/classes_objects("`Classes/Objects`") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/exceptions("`Exceptions`") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/arraylist("`ArrayList`") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/annotation("`Annotation`") subgraph Lab Skills java/collections_methods -.-> lab-117989{{"`Mockito 中的 Spy`"}} java/classes_objects -.-> lab-117989{{"`Mockito 中的 Spy`"}} java/exceptions -.-> lab-117989{{"`Mockito 中的 Spy`"}} java/arraylist -.-> lab-117989{{"`Mockito 中的 Spy`"}} java/annotation -.-> lab-117989{{"`Mockito 中的 Spy`"}} end

创建一个 Java 类

~/project 目录下创建一个名为 MockitoSpyDemo.java 的新 Java 文件。将以下代码复制到文件中。

import org.junit.Test;
import org.junit.Before;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import static org.junit.Assert.*;

public class MockitoSpyDemo {

}

使用 Mockito.spy() 方法

使用 Mockito.spy() 方法为 ArrayList 创建一个 spy。在 @Test 方法中,向 spy ArrayList 添加元素,并使用 Mockito.verify() 方法验证交互是否发生。

@Test
public void testSpyWithMockitoSpyMethod() {
    ArrayList<Integer> arrList = new ArrayList<>();
    ArrayList<Integer> spyArrList = Mockito.spy(arrList);

    //Adding Elements
    spyArrList.add(5);
    spyArrList.add(10);
    spyArrList.add(15);

    //Verifying interactions
    Mockito.verify(spyArrList).add(5);
    Mockito.verify(spyArrList).add(10);
    Mockito.verify(spyArrList).add(15);

    //Verifying that elements were actually added to the list
    assertEquals(3, spyArrList.size());
}

在终端中运行以下命令来执行代码:

javac MockitoSpyDemo.java && java MockitoSpyDemo

使用 @Spy 注解

使用 @Spy 注解为 ArrayList 创建一个 spy 对象。在 @Before 方法中使用 MockitoAnnotations.initMocks(this) 方法来初始化 spy 对象。在 @Test 方法中,向 spy ArrayList 添加元素,并使用 Mockito.verify() 方法验证交互是否发生。

//Using @Spy Annotation
@Spy
ArrayList<Integer> spyArrList = new ArrayList<>();

@Before
public void init() {
    MockitoAnnotations.initMocks(this);
}

@Test
public void testSpyWithAtSpyAnnotation() {
    spyArrList.add(5);
    spyArrList.add(10);
    spyArrList.add(15);

    Mockito.verify(spyArrList).add(5);
    Mockito.verify(spyArrList).add(10);
    Mockito.verify(spyArrList).add(15);

    assertEquals(3, spyArrList.size());
}

在终端中运行以下命令来执行代码:

javac MockitoSpyDemo.java && java MockitoSpyDemo

使用 @RunWith(MockitoJUnitRunner.class)

使用 @RunWith(MockitoJUnitRunner.class) 注解创建一个新的测试方法。使用 @Spy 注解为 ArrayList 创建一个 spy 对象。在测试方法中,向 spy ArrayList 添加元素,并使用 Mockito.verify() 方法验证交互是否发生。

@RunWith(MockitoJUnitRunner.class)
public class MockitoSpyDemo {

    //Using @Spy Annotation
    @Spy
    ArrayList<Integer> spyArrList = new ArrayList<>();

    @Test
    public void testSpyWithRunWithAnnotation() {
        spyArrList.add(5);
        spyArrList.add(10);
        spyArrList.add(15);

        Mockito.verify(spyArrList).add(5);
        Mockito.verify(spyArrList).add(10);
        Mockito.verify(spyArrList).add(15);

        assertEquals(3, spyArrList.size());
    }
}

在终端中运行以下命令来执行代码:

javac MockitoSpyDemo.java && java MockitoSpyDemo

对 Spy 进行 Stubbing

创建一个新的测试方法来演示如何对 spy 进行 stubbing。使用 Mockito.spy() 方法为 ArrayList 创建一个 spy 对象。向 spy 对象添加一个元素,并验证 contains() 方法的默认行为。然后,编写一个 stub 来覆盖 contains() 方法的默认行为,使其对于值 5 始终返回 false,并验证 stubbed 行为。

@Test
public void testStubbingSpy() {
    ArrayList<Integer> spyArrList = Mockito.spy(new ArrayList<>());
    spyArrList.add(5);

    Mockito.verify(spyArrList).add(5);
    assertEquals(true, spyArrList.contains(5));//Default normal behavior

    Mockito.doReturn(false).when(spyArrList).contains(5);
    assertEquals(false, spyArrList.contains(5));//Stubbed Behavior
}

在终端中运行以下命令来执行代码:

javac MockitoSpyDemo.java && java MockitoSpyDemo

Mock 与 Spy 在 Mockito 中的区别

创建一个新的测试方法来演示 mock 和 spy 对象之间的区别。为 ArrayList 创建一个 mock 和一个 spy 对象。向两个对象添加一个元素并验证交互是否发生。验证列表的大小。mock 列表的大小应为零,因为 add 方法没有执行任何操作,而 spy 的大小应为 1,表明 add 方法正常工作。

@Test
public void testMockVsSpy() {
    //Creating a spy and a mock
    ArrayList<Integer> spyArrList = Mockito.spy(new ArrayList<Integer>());
    ArrayList<Integer> mockArrList = Mockito.mock(ArrayList.class);

    //Adding an element to spy and mock
    spyArrList.add(5);
    mockArrList.add(5);

    //Verifying the interaction
    Mockito.verify(spyArrList).add(5);
    Mockito.verify(mockArrList).add(5);

    //verifying the size of the spy and the mock
    assertEquals(1, spyArrList.size());
    assertEquals(0, mockArrList.size());
}

在终端中运行以下命令来执行代码:

javac MockitoSpyDemo.java && java MockitoSpyDemo

Mockito 的 NotAMockException

创建一个新的测试方法来演示 NotAMockException。使用一个 ArrayList 并尝试在其上使用 verify 方法。由于 ArrayList 不是 mock 对象,因此会抛出 NotAMockException,并且无法在其上使用 verify 方法。该异常还会附带关于如何正确使用该方法的建议。

@Test(expected = NotAMockException.class)
public void testNotAMockException() {
    ArrayList<Integer> arrList = new ArrayList<>();
    arrList.add(5);
    Mockito.verify(arrList).add(5);//NotAMockException
}

在终端中运行以下命令来执行代码:

javac MockitoSpyDemo.java && java MockitoSpyDemo

总结

在本实验中,我们学习了 Mockito 框架中的 Spy 对象,它们类似于具有完整对象功能的部分 mock。我们使用 Mockito.spy() 方法和注解创建了 spy,对 Spy 进行了 stubbing 以覆盖方法的默认行为,并演示了 mock 和 spy 对象之间的区别。我们还了解了 NotAMockException,如果未正确使用 Mockito 方法,则会抛出此异常。

您可能感兴趣的其他 Java 教程