当前位置: 首页 > news >正文

使用Mockito实现单元测试

目录

1.常用注解

@RunWith

@Test

@Before 和 @After

@Mock

@Spy

@Captor

@InjectMocks

2.Mockito常用方法

Mockito.any(Class type)

Mockito.eq()

Mockito.when()

Mockito.mock(Class classToMock)

Mockito.doReturn()

Mockito.verify()

Mockito.reset

mock 异常和void处理:


       

        Mockito 是一个流行的 Java 单元测试框架,用于模拟(mock)对象以便进行单元测试。它可以帮助开发人员创建和管理模拟对象,以便在测试过程中替换那些不容易构造或获取的对象,从而达到测试被测代码的行为,而无需依赖于实际的外部系统或服务。

      相信很多公司都不会做单元测试,觉得耗时且收益低,随着AI辅助工具流行,通过AI工具可以很简答的实现单元测试。 例如图中通过通义灵码帮助完成单元测试代码,在项目降低了程序中的缺陷,而单元测试花费时间大幅度下降。在一定程度上提高了开发人员投入产生的收益。这也许是AI对软件工程最直观的影响

Mockito 的主要特点包括:

  • 模拟对象:Mockito 允许创建模拟对象,这些模拟对象具有与真实对象相似的行为,但实际上只是虚拟的对象实例。通过模拟对象,可以模拟外部依赖、交互行为等,从而使测试更加独立和可控。
  • 验证行为:Mockito 提供了丰富的 API 来验证模拟对象的交互行为,例如方法是否被调用、调用次数、参数匹配等。通过验证行为,可以确保被测代码按预期执行了与外部系统的交互。
  • Stubbing 方法:Mockito 允许对模拟对象的方法进行 Stubbing,即定义当调用某个方法时应该返回的值。这样可以模拟不同的场景和条件,以覆盖多种测试情况。
  • 灵活性:Mockito 提供了简洁且易于使用的 API,支持与 JUnit、TestNG 等测试框架集成。同时,它还提供了丰富的功能和扩展,可以满足各种测试场景的需求。

Mockito依赖

testImplementation group: 'junit', name: 'junit', version: '4.12' testImplementation group: 'org.mockito', name: 'mockito-core', version: '3.1.0'

1.常用注解

@RunWith

@RunWith注解用于在JUnit测试中指定运行器(Runner),常用的有以下两种

@RunWith(MockitoJUnitRunner.class):

@RunWith(MockitoJUnitRunner.class) 是Mockito框架提供的JUnit运行器,用于运行使用Mockito进行单元测试的类。

当使用 @RunWith(MockitoJUnitRunner.class) 注解一个测试类时,Mockito会自动初始化这个类中使用 @Mock、@InjectMocks 等注解创建的模拟对象。

这样可以简化测试类的设置过程,使得在测试中可以直接使用模拟对象而不需要手动初始化。

@RunWith(MockitoJUnitRunner.class)
public class ProductBillStartDateGetterTest {

}

@Test

标记测试方法,被 @Test 注解标记的方法会被 JUnit 的运行器执行,作为测试方法进行测试。

@Test 
public void getBillStartDate_StrategyIsNull_nullStrategy() {
 
 }

@Before 和 @After

JUnit 提供的注解,在每个测试方法执行之前和之后分别执行一段代码。通常用于设置测试的前置条件或进行资源的清理工作。

@Before
public void setUp() {
    mockAction = new Action();
    mockAction.setActionType(mock(ActionType.class));
    
    purchaseDT =new Date();
    productBillStartDateGetter = new ProductBillStartDateGetter(purchaseDT, businessBillService, strategyService);
}

@Mock

创建一个模拟对象,并注入到测试类中。通常和 @InjectMocks 注解一起使用,用于为测试类中的被测对象注入模拟对象。当你使用 @Mock 注解一个对象时,Mockito 会为你创建一个该对象的模拟实例。这个模拟实例的行为(即方法的返回值和它们被调用的方式)可以被精确地控制和验证。默认情况下,模拟对象上的所有方法调用都会返回 null(对于引用类型)或默认值(对于原始类型)。你可以使用 when(…).thenReturn(…)、when(…).thenThrow(…) 等 Mockito 方法来定义模拟对象的行为。

@Spy

用于创建一个部分模拟对象,与@Mock不同,@Spy创建的是一个实际对象的代理,并且允许你选择性地模拟对象中的某些方法。默认情况下,所有未被特别模拟的方法都会调用实际对象的方法,

通常与doReturn/doThrow等方法结合使用。

@Captor

用于捕获方法参数,以便验证方法调用参数是否正确。

@InjectMocks

注入被测对象,并自动将 @Mock 和 @Spy 标注的对象注入到被测对象中。

@RunWith(MockitoJUnitRunner.class)
public class ServiceContextTest {

    @Mock
    private IProdProvExService prodProvExService;
    @Mock
    private OpenDeviceHelper openDeviceHelper;
    @InjectMocks
    private ServiceContext serviceContext;
    
    
    }

2.Mockito常用方法

Mockito.any(Class type)

Mockito.any(Class type) 用于创建一个匹配任意指定类型的参数的匹配器。在设置模拟对象方法的行为时,我们经常会使用 Mockito.any() 来匹配任意参数。

下面是 Mockito.any() 方法的一些常见用法:

Mockito.eq()

Mockito.eq() 用于创建一个匹配特定参数值的匹配器。当你想在模拟对象的方法调用中匹配一个特定的参数时,你可以使用 eq。它通常与 when 和 verify 等方法一起使用。

Mockito.when()

Mockito.when() 是 Mockito 框架中的一个方法,用于设置模拟对象的方法调用行为。它通常与 thenReturn()、thenThrow() 或 thenAnswer() 方法一起使用。

Mockito.when(mock.methodCall()).thenReturn(value) 的语法表示当模拟对象的 methodCall() 方法被调用时,应该返回指定的 value 值。

//1.返回空
when(strategyService.locateProductBillingEntitleDateStrategy(anyLong(), anyLong(), eq(StrategyType.BeginChargeDate))).thenReturn(null);

//2.返回1个值
Strategy strategy = new Strategy();
strategy.setStrategyDetail(StrategyDetail.OrderDoneDateBegin);
when(strategyService.locateProductBillingEntitleDateStrategy(anyLong(), anyLong(), eq(StrategyType.BeginChargeDate))).thenReturn(strategy);

//3.第一次返回strategy1和第2次返回strategy2
when(strategyService.locateProductBillingEntitleDateStrategy(anyLong(), anyLong(), eq(StrategyType.BeginChargeDate))).thenReturn(strategy1).thenReturn(strategy2);

//4.返回集合有1个值
when(subscriberExtInfoDao.querySubscriberExtInfoByCondition(any())).thenReturn(Collections.singletonList(subscriberAddon));

//5.返回空集合
when(orderItemContext.getSubscriberContexts()).thenReturn(Collections.emptyList());

Mockito.mock(Class classToMock)

用于创建一个指定类的模拟对象

@Test
public void getBillStartDate_StrategyIsNull_nullStrategy() {
    when(strategyService.locateProductBillingEntitleDateStrategy(anyLong(), anyLong(), eq(StrategyType.BeginChargeDate))).thenReturn(null);
    AbstractProduct product = mock(AbstractProduct.class);
    Date result = productBillStartDateGetter.getBillStartDate(product, mockAction);
    assertEquals(DateUtils.getBeginOfDate(purchaseDT), result);
}

Mockito.doReturn()

Mockito.doReturn() 用于设置模拟对象方法的返回值。与 Mockito.when().thenReturn() 方法类似,Mockito.doReturn() 也用于模拟方法调用时的返回结果,但在某些特定情况下会更加灵活和有效。

以下是 Mockito.doReturn() 方法的一些常见用法:

设置模拟对象方法的返回值:

// 使用 doReturn() 设置 getUserById() 方法的返回值
Mockito.doReturn(new User("Alice")).when(userServiceMock).getUserById(1);

Mockito.verify()

Mockito.verify(): 用于验证模拟对象的方法是否被调用以及调用的次数。它通常与 times()、atLeastOnce()、never() 等方法一起使用。

Mockito.verify(mock, times(n)).methodCall() 的语法表示验证模拟对象的 methodCall() 方法被调用了 n 次。

@Test
public void getBillStartDate_StrategyDetailOrderDoneDateBegin_OrderDoneDateBegin() {
    Strategy strategy = new Strategy();
    strategy.setStrategyDetail(StrategyDetail.OrderDoneDateBegin);

    when(strategyService.locateProductBillingEntitleDateStrategy(anyLong(), anyLong(), eq(StrategyType.BeginChargeDate))).thenReturn(strategy);
    AbstractProduct product = mock(AbstractProduct.class);
    Date result = productBillStartDateGetter.getBillStartDate(product, mockAction);

    assertEquals(DateUtils.getBeginOfDate(purchaseDT), result);
    Mockito.verify(businessBillService, never()).getInvoiceCyc(any(Date.class),anyInt());
    Mockito.verify(strategyService, times(1)).locateProductBillingEntitleDateStrategy(anyLong(), anyLong(), any(StrategyType.class));
    Mockito.verify(strategyService).locateProductBillingEntitleDateStrategy(anyLong(), anyLong(), any(StrategyType.class));
}

Mockito.reset

Mockito.reset(mock):重置模拟对象的状态,清除之前的交互和验证。

mock 异常和void处理:

// 设置 delete() 方法为无返回值时的行为
Mockito.doNothing().when(userServiceMock).deleteUser(1);
// 设置 void 方法抛出异常时的行为
Mockito.doThrow(new RuntimeException("Unable to delete user")).when(userServiceMock).deleteUser(2);
Mockito.when(userServiceMock.saveUser(null)).thenThrow(new IllegalArgumentException("Invalid parameter"));

//断言异常
assertThrows(MsrRuntimeException.class, () -> cmResourceChecker.checkHaveCmSubscriberAddon(orderItemContext));


相关文章:

  • Bootstrap:图标库的安装及其使用
  • spring boot和spring cloud的区别
  • 【0016】Python数据类型-不可变集合详解
  • Retouch Pro 3.2.0汉化版深度解析:AI智能人像修图新利器
  • 开源许可证通俗、简洁介绍
  • K8s 1.27.1 实战系列(八)Service
  • 5G基本概念
  • fiddler+雷电模拟器(安卓9)+https配置
  • 计算机网络--访问一个网页的全过程
  • 从Manus看网络安全:通用AI智能体重构安全运营
  • gdb调试以及常用相关工具(hexdump\objdump等)
  • Node.js与VUE安装
  • 化工厂防爆气象站:为石油化工、天然气等领域提供安全保障
  • 在 Axios 中设置代理
  • BGP实验(一)IBGP全互联配置
  • Android TCP封装工具类
  • 【Linux docker】关于Docker 守护程序配置远程访问,安全认证以及idea连接。
  • 高效获取历史行情数据:xtquant的实战应用
  • SpringCloud——CircuitBreaker断路器
  • 电脑维修保养售后服务跟踪软件到哪里下载,佳易王电脑保养维护记录查询可导入图片管理系统操作教程
  • 国务院安委会办公室印发通知:坚决防范遏制重特大事故发生
  • 世界人形机器人运动会将在北京“双奥场馆”举行
  • 新疆生产建设兵团草湖项目区副主任宋全伟接受审查调查
  • 恒瑞医药通过港交所上市聆讯,最快或5月挂牌上市
  • 中虎跳峡封闭仍有游客逆行打卡,景区:专人值守防意外
  • 消息人士称以色列政府初步同意扩大对加沙军事行动