mockito-关于@Mock和@Spy的使用方法

 

mockito-关于@Mock和@Spy的使用方法

  1091人阅读  评论(0)  收藏  举报
  分类:

参考:http://site.mockito.org/mockito/docs/current/org/mockito/Mockito.html

当我们对@Mock的类(@Mock private OrderDao dao;)进行模拟方法时,会像下面这样去做:

    when(dao.getOrder()).thenReturn("returened by mock "); // 或者使用更为推荐的given方法

但如果想对@Spy的类(@Spy private PriceService ps;)进行模拟方法时,需要像下面一样去做:

    doReturn("twotwo").when(ps).getPriceTwo();

原因:

使用@Mock生成的类,所有方法都不是真实的方法,而且返回值都是NULL。

使用@Spy生成的类,所有方法都是真实方法,返回值都是和真实方法一样的。

所以,你用when去设置模拟返回值时,它里面的方法(dao.getOrder())会先执行一次。

使用doReturn去设置的话,就不会产生上面的问题,因为有when来进行控制要模拟的方法,所以不会执行原来的方法。


### Java Mockito 中 `@Mock` `@Spy` 的区别及使用场景 #### 1. 基本概念 - **`@Mock`**: 创建一个完全由 Mockito 控制的对象,该对象的行为可以通过定义来进行模拟。它会调用实际的方法逻辑,而是返回默认值或抛出异常[^1]。 - **`@Spy`**: 创建一个部分模拟的对象,允许调用真实方法的同时可以对某些行为进行拦截修改。与 `@Mock` 同的是,未被 stub 的方法会执行其原始实现[^3]。 --- #### 2. 行为差异 -使用 `@Mock` 注解时,Mockito 完全接管目标类的实例化过程,并提供了一个虚拟化的代理对象。这意味着如果没有显式地指定某个方法的行为,则此方法将始终返回默认值(如 null 或者 false)。例如: ```java @Mock private SomeService someService; when(someService.doSomething()).thenReturn("mocked"); ``` - 而对于标记有 `@Spy` 的字段来说,默认情况下仍然保留原有功能变;但是我们同样能够通过设置期望值得方式改变特定操作的结果。比如下面的例子展示了如何让 spy 对象中的某一部分保持原样工作,另一些地方则按照我们的需求定制响应数据: ```java @Spy private List<String> list = new ArrayList<>(); doReturn(true).when(list).isEmpty(); // 修改 isEmpty 方法的行为 ``` 上述代码片段表明即使列表内部确实存在元素,在测试期间调用 isEmpty() 将总是得到 true 返回值[^2]。 --- #### 3. 初始化要求 无论是采用哪种形式都需要确保适当初始化机制的存在以便于框架识别相应的注释标签并将关联属性正确配置成对应的 mock/spy 实体。一般有两种途径可供选择:一是利用 JUnit Runner 扩展支持自动完成这一任务;二是手动调用 initMocks 方法自行处理相关事宜。 ```java // Option A: Using RunWith Annotation (Recommended Approach) @RunWith(MockitoJUnitRunner.class) public class MyTest {} // Option B: Manual Initialization Inside Setup Method @BeforeEach void setUp(){ MockitoAnnotations.openMocks(this); } ``` --- #### 4. 使用场景对比 | 特性/适用范围 | `@Mock` | `@Spy` | |---------------|---------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------| | 主要用途 | 替代依赖项以验证交互关系 | 部分替换依赖项的功能 | | 默认行为 | 所有的方法都返回预设值(0, "", Collections.emptyList(), etc.) | 只有那些被 stubbed 的方法才会有特殊表现;其他均按正常流程运行 | | 是否需要实例化| 否 | 是 | 因此当仅需关注接口或者抽象类间相互作用而关心具体业务细节的时候可以选择前者(`@Mock`)简化开发难度提升效率;反之如果既希望维持大部分既有能力又想局部调整个别环节的话后者(`@Spy`)无疑更加合适一些。 --- ### 示例代码展示 以下是两个简单的例子分别演示了这两种技术的应用场合: #### Example with `@Mock` ```java @Test public void testMockBehavior(){ @Mock Service service; given(service.performAction(anyString())).willReturn("Success"); assertEquals("Success",service.performAction("test")); } ``` #### Example with `@Spy` ```java @Test public void testSpyBehavior(){ @Spy Repository repository=new InMemoryRepository(); repository.save(new Entity()); verify(repository,times(1)).save(any()); assertTrue(repository.findAll().size()==1); doThrow(new RuntimeException()).when(repository).deleteAll(); assertThrows(RuntimeException.class,()->repository.deleteAll()); } ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值