Mockito mock与spy的区别

本文通过示例对比了Mockito中mock与spy的区别。mock主要用于模拟对象行为而不真正执行,而spy则会在测试中调用真实的方法。

##前言

Mockito是一个强大的mock工具,本文将重点讲述Mockito中mock与spy的区别

mock与spy的区别

mock跟spy都可以用于模拟对象,区别是mock产生的对象,并不会真正的执行对象的行为,而spy创建的对象,会真的去执行对象的行为

示例:

@Test
public void mockitoTest2(){
//生成一个mock对象
List<String> mockedList = Mockito.mock(ArrayList.class);
//打印mock对象的类名,看看mock对象为何物
System.out.println("mock List==========="+mockedList.getClass().getName());
//操作mock对象
mockedList.add("one");
System.out.println("0 agr:"+mockedList.get(0));
System.out.println("10 agr:"+mockedList.get(10));


//生成一个spy对象
List<String> spyList = Mockito.spy(ArrayList.class);
//打印mock对象的类名,看看spy对象为何物
System.out.println("spy List============"+spyList.getClass().getName());
//操作mock对象
spyList.add("one");
System.out.println("0 agr:"+spyList.get(0));
System.out.println("10 agr:"+spyList.get(10));
}

输出:

mock List===========org.mockito.codegen.ArrayList$MockitoMock$951596036
0 agr:null
10 agr:null
spy List============org.mockito.codegen.ArrayList$MockitoMock$951596036
0 agr:one

java.lang.IndexOutOfBoundsException: Index: 10, Size: 1

通过代码示例可以看出,对mockedList的操作并没有真正的去执行,而spyList会抛出异常;

Mockito 中,`@Spy` 注解和 `@Mock` 注解都是用于创建模拟对象的注解,但它们的行为和使用场景有所不同。 ### `@Mock` 注解 `@Mock` 注解用于创建一个完全模拟的对象,该对象是目标类的一个虚拟实例,不包含目标类的实际逻辑和状态。对这个模拟对象的方法调用默认不会执行真实的方法逻辑,而是返回默认值(如 `null`、`false` 等),除非对这些方法进行了显式的行为 stubbing(打桩)。 示例代码如下: ```java import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import java.util.ArrayList; import java.util.List; @RunWith(MockitoJUnitRunner.class) public class MockExample { @Mock private List<String> mockList; @Test public void testMock() { // 调用模拟对象的方法 mockList.add("element"); // 验证方法是否被调用 Mockito.verify(mockList).add("element"); // 没有 stub 时,调用 size() 方法返回默认值 0 assert mockList.size() == 0; // 对 size() 方法进行 stubbing Mockito.when(mockList.size()).thenReturn(10); assert mockList.size() == 10; } } ``` ### `@Spy` 注解 `@Spy` 注解用于创建一个真实对象的监视对象,它包装了一个真实的对象实例,会调用真实对象的方法并保留其状态。不过,我们也可以对 `@Spy` 对象的某些方法进行 stubbing,以改变其行为。`@Spy` 是 `Mockito.spy(classToMock)` 的一种替代方法,能减少样板代码,使代码更整洁 [^1]。 示例代码如下: ```java import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; import java.util.ArrayList; import java.util.List; @RunWith(MockitoJUnitRunner.class) public class SpyExample { @Spy private List<String> spyList = new ArrayList<>(); @Test public void testSpy() { // 调用真实对象的方法 spyList.add("element"); // 验证方法是否被调用 Mockito.verify(spyList).add("element"); // 调用真实对象的 size() 方法 assert spyList.size() == 1; // 对 size() 方法进行 stubbing Mockito.when(spyList.size()).thenReturn(10); assert spyList.size() == 10; } } ``` ### 区别总结 - **方法调用**:`@Mock` 对象的方法调用默认不会执行真实逻辑,而 `@Spy` 对象默认会执行真实对象的方法 [^1]。 - **初始化**:`@Mock` 创建的是虚拟对象,不需要真实对象实例;`@Spy` 需要一个真实对象实例来进行包装。 - **默认行为**:`@Mock` 对象的方法返回默认值,`@Spy` 对象的方法返回真实对象的执行结果,除非进行了 stubbing。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值