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

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

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

相关推荐
流星白龙17 小时前
【Linux】23.进程间通信(2)
linux·数据库·microsoft
流形填表1 天前
Pdf to forms如何实现?如何在3分钟内将PDF自动转换为Microsoft Forms
microsoft·pdf·c#
果冻人工智能2 天前
“星门计划对AI未来的意义——以及谁将掌控它”
大数据·人工智能·microsoft·自然语言处理·llama·ai员工
Zda天天爱打卡2 天前
【深度分析】微软全球裁员计划不影响印度地区,将继续增加当地就业机会
microsoft·创业创新
kcarly3 天前
Microsoft Power BI:融合 AI 的文本分析
人工智能·gpt·microsoft·bi
流形填表3 天前
如何使用formlinker,重构微软表单创建的数字生产力法则?
microsoft·重构·c#
R三哥哥啊4 天前
【Qt】06-对话框
开发语言·qt·microsoft·qt5
小奥超人4 天前
EXCEL教程:如何打开Excel隐藏部分?
windows·经验分享·microsoft·excel·办公技巧
涟幽5165 天前
Microsoft Visual Studio 2022 主题修改(补充)
ide·microsoft·visual studio
人才程序员5 天前
【PySide6快速入门】QFileDialog 文件选择对话框
c语言·c++·qt·microsoft·pyside6·python3.11