junit+mockito-PowerMock完成单测

Mockito简介

什么是Mockito

Mockito是一个开源的Mock框架,旨在为Java单元测试提供简单、可读的Mock对象。它可以模拟类的行为,使测试代码能够在不依赖真实对象的情况下运行。

为什么使用Mockito

  • 隔离外部依赖:可以模拟外部系统(如数据库、网络服务等),使测试更加独立。
  • 提高测试覆盖率:即使没有实现具体逻辑,也可以编写测试,确保接口和交互逻辑正确。
  • 便于测试边界条件:可以轻松模拟异常情况和边界条件,确保代码在各种情况下的稳定性。

中文文档

https://gitcode.com/bboyfeiyu/mockito-doc-zh/overview?utm_source=artical_gitcode

https://github.com/kuaile-zc/mockito-doc-zh/tree/master

单测mock

监测变量

 

 // Run the test
        final List<String> result = coldChainShipmentOrderDomainServiceImplUnderTest.createShipmentOrder(command,
            OperateContextUtil.getSystemOperator());
        //监测此变量
        ArgumentCaptor<List<ColdChainShipmentOrderAggregate>> captor = ArgumentCaptor.forClass(
            List.class);
        //内部调用此mock方法时监测
        verify(mockColdChainShipmentOrderRepository).doSave(captor.capture());
        // 获取捕获的参数值
        List<ColdChainShipmentOrderAggregate> capturedValue = captor.getValue();

        //mock的数据未经过习惯没有domainEvents
        assertThat(CollectionUtils.isNotEmpty(capturedValue) && capturedValue.size() == 1
            && capturedValue.get(0).getDomainEvents().get(0) instanceof CreateShipmentOrderDomainEvent).isTrue();

 

 状态清除

 Mockito.reset(mockRedissonLockUtil);
        Mockito.reset(mockColdChainAlarmOrderRepository);
        Mockito.reset(mockNotifyApplicationService);
        Mockito.reset(mockNotifyApplicationService);

 mock void方法抛出异常

        doThrow(new YxtRuntimeException(ResponseCodeType.BIZ_EXCEPTION)).when(mockAuthApplicationService).checkAuthByStoreCode(command.getShipperOrgCode(),
            any(OperateContext.class));

捕获

变量捕获

        //------------------------------------------------------根据发货单号进行发货----------------------------------
        // Run the test
        final List<String> result = coldChainShipmentOrderDomainServiceImplUnderTest.batchShipOrder(batchShipCommand,
            operateContext);

        ArgumentCaptor<List<ColdChainShipmentOrderAggregate>> captor = ArgumentCaptor.forClass(
            List.class);
        verify(mockColdChainShipmentOrderRepository).doSave(captor.capture());
        // 获取捕获的参数值
        List<ColdChainShipmentOrderAggregate> capturedValue = captor.getValue();
        assertThat(capturedValue.get(0).getShipmentInfo() != null).isTrue();

 

 

常用断言

断言方法被调用

  verify(mockRedissonLockUtil).unlock(lockKey);

 

断言方法未被调用

verify(mockNotifyApplicationService, never()).sendPersonMessage(any(SendPersonMessageDTO.class),
    any(OperateContext.class));

 断言抛出异常

        assertThatThrownBy(
            () -> coldChainAlarmOrderDomainServiceImplUnderTest.createAlarmOrder(command))
            .isInstanceOf(YxtRuntimeException.class).hasMessage("系统繁忙,请稍后重试!");

模拟事务

   // 发送领域事件
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
              
            }
        });

 

    @Before
    public void startTransaction() {
        if (!TransactionSynchronizationManager.isActualTransactionActive()) {
            TransactionSynchronizationManager.setActualTransactionActive(true);
            TransactionSynchronizationManager.initSynchronization();
        }
    }

 

PowerMock

mock私有方法

   // Mock 模拟私有方法
        PowerMockito.doReturn(hasAuth)
            .when(spyService, "setAuthErpOrgCodes", Mockito.any(PageAlarmOrderReqDTO.class),
                Mockito.any(PageAuthAlarmOrderCommand.class), Mockito.any(
                    OperateContext.class));

初始化私有变量

        Whitebox.setInternalState(coldChainAlarmOrderRepresentationServiceImplUnderTest, "chainBusinessOrgCode",
            chainBusinessOrgCodeValue);

 私有方法单测

  @InjectMocks
    private ReceiveApplicationServiceImpl receiveApplicationServiceImplUnderTest;
    @Test
    public void test_checkReceiveTime() {

        ReceiveApplicationServiceImpl spyService = PowerMockito.spy(
            receiveApplicationServiceImplUnderTest);
        ReceiveCommand command = ReceiveCommand.builder().receiverTime(DateHelper.getDayNow(DateHelper.now(), 1))
            .build();
        //发货信息为空场景
        ColdChainShipmentInfoEntity coldChainShipmentInfoEntity = null;
        assertThatThrownBy(
            () -> Whitebox.invokeMethod(spyService, "checkReceiveTime", command, coldChainShipmentInfoEntity))
            .isInstanceOf(YxtRuntimeException.class).hasMessage("发货信息不能为空");

        //收货时间早于发货时间场景
        ColdChainShipmentInfoEntity coldChainShipmentInfoEntityA = new ColdChainShipmentInfoEntity();
        coldChainShipmentInfoEntityA.setDepartureTime(DateHelper.getDayNow(DateHelper.now(), 2));
        assertThatThrownBy(
            () -> Whitebox.invokeMethod(spyService, "checkReceiveTime", command, coldChainShipmentInfoEntityA))
            .isInstanceOf(YxtRuntimeException.class).hasMessage("收货时间早于发货时间,不能收货");

        //收货时间大于当前时间场景
        ReceiveCommand commandB = ReceiveCommand.builder().receiverTime(DateHelper.getDayNow(DateHelper.now(), 1))
            .build();
        ColdChainShipmentInfoEntity coldChainShipmentInfoEntityB = new ColdChainShipmentInfoEntity();
        coldChainShipmentInfoEntityB.setDepartureTime(DateHelper.getDayNow(DateHelper.now(), -2));
        assertThatThrownBy(
            () -> Whitebox.invokeMethod(spyService, "checkReceiveTime", commandB, coldChainShipmentInfoEntityB))
            .isInstanceOf(YxtRuntimeException.class).hasMessage("收货时间晚于当前时间,不能收货");
    }

 

 

posted @ 2024-06-11 18:31  意犹未尽  阅读(14)  评论(0编辑  收藏  举报