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);

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

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

相关推荐
ClickHouseDB2 小时前
ClickHouse Grafana 插件更新:引入无代码查询与日志检索优化
microsoft
释厄6237 小时前
01AB 基本元理——任何智能体的三元法理·0=1→0≠1法理跃迁为天理
人工智能·windows·算法·microsoft·机器学习
执明wa9 小时前
Android RecyclerView 实战:点击频道栏切换对应内容
android·开发语言·windows·microsoft·android studio
海盗12349 小时前
微软技术日报 2026-10-02:微软首发流式转录模型,Win11 26H2 悄悄省内存
人工智能·microsoft·机器人·aigc
jnrjian10 小时前
Connect Microsoft Tools to Oracle Databases powerbi 之类的oracle 客户端
数据库·microsoft·oracle
HwJack201 天前
【共创稿事节】HarmonyOS 7空间排布原则:视锥、舒适区与可达性
microsoft·华为·harmonyos
狗凯之家源码网1 天前
AI 导航网站模板一站式工具合集源码深度评测
microsoft·ai导航系统
释厄6231 天前
物理发展史·量子力学=节点2·牛顿力学=节点3·宇宙的语言算法AI
人工智能·算法·microsoft
海盗12341 天前
微软技术日报 2026-10-01:VS Code 1.140 让模型互相挑错,EWS 今天起关停
人工智能·驱动开发·microsoft·机器人·aigc
Yan-英杰2 天前
2026年数据采集服务怎么选?4大主流平台(亮数据 Bright Data、Apify、ScrapingBee、Zyte)深度对比
人工智能·神经网络·microsoft·机器学习·ai开发工具