Mockito 的间谍
原文:https://www.studytonight.com/java-examples/spy-in-mockito
Mockito 是一个 Java 框架,用于模拟和单元测试 Java 应用。在内部,这个框架使用反射 API。Mockito 通过创建模拟对象和避免外部依赖来简化测试过程。它与其他测试框架一起使用,如 JUnit 或 TestNG 。
在本教程中,我们将了解 Mockito 的间谍。
莫基托间谍
间谍就像一个局部模拟,它会像模拟一样跟踪与对象的交互。此外,它允许我们调用对象的所有正常方法。每当我们调用间谍对象的一个方法时,真正的方法就会被调用(除非它被存根化)。
使用 Mockito.spy()方法创建间谍
在下面的代码中,我们为ArrayList
创建了一个间谍。Mockito.spy()方法用于此目的。验证()方法用于验证交互是否发生。当对间谍调用 add()方法时,将调用实际的方法,并将元素添加到列表中。我们可以通过查看列表的大小来验证它。
public class MockitoSpyDemo
{
@Test
public void test()
{
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());
}
}
使用@间谍注释创建间谍
我们也可以使用@Spy 注释创建一个间谍对象。要启用 Mockito 注释,我们可以使用mockitonations . init mocks(this)方法。或者我们可以使用内置的 runner@ RunWith(mockitojunitrunner . class)。两者的示例如下所示。
使用模拟注释
public class MockitoSpyDemo
{
//Using @Spy Annotation
@Spy
ArrayList<Integer> spyArrList = new ArrayList<>();
@Before
public void init()
{
MockitoAnnotations.initMocks(this);
}
@Test
public void test()
{
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());
}
}
使用@ RunWith(mockitojunitrunner . class)
@RunWith(MockitoJUnitRunner.class)
public class MockitoSpyDemo
{
//Using @Spy Annotation
@Spy
ArrayList<Integer> spyArrList = new ArrayList<>();
@Test
public void test()
{
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());
}
}
干掉一名间谍
我们可以截取一个间谍来覆盖一个方法的正常行为。让我们覆盖 ArrayLists 的 contains()方法的默认行为。让我们让这个方法总是为值 5 返回 false。
public class MockitoSpyDemo
{
@Test
public void test()
{
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
}
}
让我们覆盖ArrayList
的 size()方法。它应该总是返回 5 作为列表大小。
public class MockitoSpyDemo
{
@Test
public void test()
{
ArrayList<Integer> spyArrList = Mockito.spy(new ArrayList<>());
spyArrList.add(5);
Mockito.verify(spyArrList).add(5);
assertEquals(1, spyArrList.size());//Default Normal Behavior
Mockito.doReturn(5).when(spyArrList).size();
assertEquals(5, spyArrList.size());//Stubbed Behavior
}
}
Mockito 的模拟 vs 间谍
间谍被称为部分嘲讽。模拟是从一个类型的类中创建的,而间谍是从类的实际实例中创建的。在模拟的情况下,类的所有正常方法都不会被执行。另一方面,间谍会使用原始行为的方法。方法执行的结果也反映在间谍对象上。
例如,在下面的代码中,我们有一个模拟和一个间谍。两个对象都验证了交互。但是当 add()方法被调用时,一个元素只被添加到间谍列表中。模拟列表的大小为零,表明 add()方法没有做任何事情。
public class MockitoSpyDemo
{
@Test
public void test()
{
//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());
}
}
莫基托注意到异常
使用 Mockito 时,经常会遇到 NotAMockException。当我们试图在其他对象上使用模拟特定的方法时,会引发此异常。例如,在下面的代码中,我们创建了一个ArrayList
,但它不是模拟的。当我们对其使用 verify()方法时,会引发 NotAMockException。正如异常的名称所示,ArrayList
不是模拟的,我们不能对它使用 verify()方法。例外情况还附带了一些如何使用该方法的建议。
public class MockitoSpyDemo
{
@Test
public void test()
{
ArrayList<Integer> arrList = new ArrayList<>();
arrList.add(5);
Mockito.verify(arrList).add(5);//NotAMockException
}
}
org . mock ITO . exceptions . misusing . nota mock exception: 传递给 verify()的参数属于 ArrayList 类型,不是 mock! 确保括号放置正确! 参见正确验证示例: 验证(模拟)。some method(); 验证(模拟,次数(10))。some method(); 验证(模拟,至少测试())。some method(); 在 Demo.test(Demo.java:15)
摘要
Mockito 框架用于 Java 应用的单元测试。在本教程中,我们学习了 Mockito 框架的间谍对象。与模拟不同,间谍执行对象的真实方法,方法的结果也反映在对象中。我们还了解了 NotAMockException,如果 Mockito 方法使用不当,就会引发该异常。