Mockito

1.什么是Mockito?

Mockito 是一个强大的 Java 测试框架,专门用于创建和管理模拟对象。它允许我们:

  • 创建模拟对象:通过简单的语法创建对象的模拟版本。
  • 定义行为:设置模拟对象的方法返回值或抛出异常。
  • 验证交互:验证某些方法是否被调用,或调用了几次。

1.1Mockito的核心功能

  • 模拟(Mocking):创建一个类或接口的模拟对象。
  • 桩方法(Stubbing):定义模拟对象的方法行为,例如返回特定值或抛出异常。
  • 验证(Verification):检查模拟对象的方法是否按照预期被调用。

2.引入Mockito

要在项目中使用 Mockito,我们首先需要在 pom.xml 中添加其依赖:

java 复制代码
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>4.0.0</version>
    <scope>test</scope>
</dependency>

3.一个简单的Mockito测试

例:银行转账服务

我们有一个银行转账服务 TransferService,它依赖于一个账户服务 AccountService 来完成实际的资金转移。在测试转账功能时,我们不希望真的去修改账户中的金额,因此可以使用 Mockito 来模拟 AccountService。

被测试类 TransferService.java:

java 复制代码
public class TransferService {

    private AccountService accountService;

    public TransferService(AccountService accountService) {
        this.accountService = accountService;
    }

    public boolean transfer(String fromAccount, String toAccount, double amount) {
        if (accountService.withdraw(fromAccount, amount)) {
            return accountService.deposit(toAccount, amount);
        }
        return false;
    }
}

依赖类 AccountService.java:

java 复制代码
public interface AccountService {
    boolean withdraw(String account, double amount);
    boolean deposit(String account, double amount);
}

测试类 TransferServiceTest.java:

java 复制代码
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

public class TransferServiceTest {

    private AccountService accountService;
    private TransferService transferService;

    @Before
    public void setUp() {
        accountService = Mockito.mock(AccountService.class); // 创建AccountService的模拟对象
        transferService = new TransferService(accountService); // 传入模拟对象
    }

    @Test
    public void testTransferSuccess() {
        when(accountService.withdraw("123", 100.0)).thenReturn(true); // 设置 withdraw 方法的返回值
        when(accountService.deposit("456", 100.0)).thenReturn(true);   // 设置 deposit 方法的返回值

        boolean result = transferService.transfer("123", "456", 100.0);

        assertTrue(result); // 断言转账成功
        verify(accountService).withdraw("123", 100.0); // 验证 withdraw 方法被调用
        verify(accountService).deposit("456", 100.0);  // 验证 deposit 方法被调用
    }

    @Test
    public void testTransferFailure() {
        when(accountService.withdraw("123", 100.0)).thenReturn(false); // 模拟 withdraw 失败

        boolean result = transferService.transfer("123", "456", 100.0);

        assertFalse(result); // 断言转账失败
        verify(accountService).withdraw("123", 100.0); // 验证 withdraw 被调用
        verify(accountService, never()).deposit(anyString(), anyDouble()); // 验证 deposit 没有被调用
    }
}

解释:

  1. 创建模拟对象 :使用 Mockito.mock(AccountService.class) 创建 AccountService
    的模拟对象。
  2. 设置桩方法 :通过 when(...).thenReturn(...) 方法,定义模拟对象的方法返回特定值。例如:当
    withdraw 方法被调用时,返回 true。
  3. 验证交互 :使用 verify(...) 来验证特定方法是否被调用,以及调用次数。在
    testTransferSuccess 中,我们验证了 withdraw 和 deposit 方法都被正确调用。

4.Mockito常用功能

4.1模拟异常

在测试错误处理逻辑时,模拟方法抛出异常也很有用。Mockito 提供了 thenThrow() 来模拟异常行为。

java 复制代码
@Test(expected = RuntimeException.class)
public void testWithdrawThrowsException() {
    when(accountService.withdraw("123", 100.0)).thenThrow(new RuntimeException("Insufficient funds"));
    
    transferService.transfer("123", "456", 100.0);
}

4.2参数匹配

Mockito 提供了多种参数匹配器,用于更加灵活地模拟方法。例如:

  • anyString():匹配任意字符串。
  • anyDouble():匹配任意 double 类型参数。
  • eq(value):匹配指定的值。
java 复制代码
when(accountService.deposit(anyString(), eq(100.0))).thenReturn(true);

4.3验证调用次数

可以验证方法是否被调用了指定次数:

java 复制代码
verify(accountService, times(1)).withdraw("123", 100.0); // 验证 withdraw 方法被调用一次

4.4重置模拟对象

有时需要重置模拟对象的状态,Mockito 提供了 reset() 方法:

java 复制代码
verify(accountService, times(1)).withdraw("123", 100.0); // 验证 withdraw 方法被调用一次

4.5重置模拟对象

有时我们需要重置模拟对象的状态,Mockito 提供了 reset() 方法:

java 复制代码
reset(accountService);

有兴趣的小伙伴可以关注我的公众号【知识星球站】一起讨论学习!!

独自行走江湖路,心怀壮志闯天涯。

相关推荐
专注VB编程开发20年6 小时前
无需安装Office进行 Word、Excel操作的微软开发库
microsoft·word·excel
双叶83614 小时前
(C语言)虚数运算(结构体教程)(指针解法)(C语言教程)
c语言·开发语言·数据结构·c++·算法·microsoft
笑鸿的学习笔记19 小时前
ROS2笔记之服务通信和基于参数的服务通信区别
android·笔记·microsoft
鲤籽鲲1 天前
C# System.Net.IPEndPoint 使用详解
网络·microsoft·c#·.net
双叶8362 天前
(C语言)学生信息表(学生管理系统)(基于通讯录改版)(正式版)(C语言项目)
c语言·开发语言·c++·算法·microsoft
weixin_409411022 天前
支持 MCP 协议的开源 AI Agent 项目
人工智能·microsoft
office大师姐5 天前
迈向云数据领域的第一步:Microsoft Azure DP-900认证指南
大数据·windows·microsoft·微软·azure
zhou周大哥5 天前
轮循取值算法数据库
linux·windows·microsoft
塞大花5 天前
微软 GraphRAG 项目学习总结
人工智能·microsoft·语言模型·大语言模型·rag·knowledge graph·graphrag
她说彩礼65万5 天前
WPF ContentTemplate
microsoft·wpf