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

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



http://www.kler.cn/a/580233.html

相关文章:

  • 国产编辑器EverEdit - 脚本(解锁文本编辑的无限可能)
  • 自然语言处理入门3——Embedding和神经网络加速计算
  • 云计算网络学习笔记整理
  • flutter EventBus 的使用介绍
  • c# 使用Md5加密字符串
  • Docker篇
  • Elasticsearch 提升查询精度
  • ca证书和服务端证书两者之间的关系
  • 论文阅读分享——UMDF(AAAI-24)
  • 【VMware安装Ubuntu实战分享】
  • C语言笔记(通讯录)
  • Linux系统的安全加固与安全防护
  • postgresql json和jsonb问题记录
  • 基于物联网技术的分布式光伏监控系统设计与实现
  • 【STM32】ADC功能-单通道多通道(学习笔记)
  • 面试题之vue和react的异同
  • 机电公司管理信息系统小程序+论文源码调试讲解
  • Electron应用中获取设备唯一ID和系统信息
  • 中国证监会主席吴清:进一步优化差异化安排 更精准支持优质科技企业上市
  • springboot-自定义注解