《Java单元测试实战》——案例集锦:Java单元测试典型案例集锦(10)

简介: 《Java单元测试实战》——案例集锦:Java单元测试典型案例集锦(10)

《Java单元测试实战》——案例集锦:Java单元测试典型案例集锦(9) https://developer.aliyun.com/article/1232050?groupCode=java



十、 如何测试多线程并发编程

 

Java多线程并发编程,就是通过多个线程同时执行多个任务来缩短执行时间、提高执行效率的方法。在JDK1.8中,新增了CompletableFuture类,实现了对任务编排的能力——可以轻松地组织不同任务的运行顺序、规则及方式。

 

1. 案例代码

这里,以并行获取批量交易订单为例说明。


/**
 * 交易订单服务类
 */
@Slf4j
@Service
public class TradeOrderService {
    /** 定义静态常量 */
    /** 等待时间(毫秒) */
    private static final long WAIT_TIME = 1000L;
    /** 注入依赖对象 */
    /** 交易订单DAO */
    @Autowired
    private TradeOrderDAO tradeOrderDAO;
    /** 执行器服务 */
    @Autowired
    private ExecutorService executorService;
    /**
     * 获取交易订单列表
     * 
     * @param orderIdList 订单标识列表
     * @return 交易订单列表
     */
    public List<TradeOrderVO> getTradeOrders(List<Long> orderIdList) {
        // 检查订单标识列表
        if (CollectionUtils.isEmpty(orderIdList)) {
            return Collections.emptyList();
        }
        // 获取交易订单期望
        List<CompletableFuture<TradeOrderVO>> futureList = orderIdList.stream()
            .map(this::getTradeOrder).collect(Collectors.toList());
        // 聚合交易订单期望
        CompletableFuture<List<TradeOrderVO>> joinFuture =
            CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0]))
                .thenApply(v -> futureList.stream().map(CompletableFuture::join).collect(Collectors.toList()));
        // 返回交易订单列表
        try {
            return joinFuture.get(WAIT_TIME, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.warn("获取订单中断异常", e);
            throw new BusinessException("获取订单中断异常", e);
        } catch (ExecutionException | TimeoutException | RuntimeException e) {
            log.warn("获取订单其它异常", e);
            throw new BusinessException("获取订单其它异常", e);
        }
    }
    /**
     * 获取交易订单
     * 
     * @param orderId 订单标识
     * @return 交易订单期望
     */
    private CompletableFuture<TradeOrderVO> getTradeOrder(Long orderId) {
        return CompletableFuture.supplyAsync(() -> tradeOrderDAO.get(orderId), executorService)
            .thenApply(TradeOrderService::convertTradeOrder);
    }
    /**
     * 转化交易订单
     * 
     * @param tradeOrder 交易订单DO
     * @return 交易订单VO
     */
    private static TradeOrderVO convertTradeOrder(TradeOrderDO tradeOrder) {
        TradeOrderVO tradeOrderVO = new TradeOrderVO();
        tradeOrderVO.setId(tradeOrder.getId());
        // ...
        return tradeOrderVO;
    }
}

2. 测试用例

 

对于多线程并发编程,如果采集mock静态方法的方式进行单元测试,将会使单元测试用例变得非常复杂。通过实践总结,采用注入线程池的方式,将会使单元测试用例变得非常简单。


/**
 * 交易订单服务测试类
 */
@RunWith(MockitoJUnitRunner.class)
public class TradeOrderServiceTest {
    /** 定义静态常量 */
    /** 资源路径 */
    private static final String RESOURCE_PATH = "testTradeOrderService/";
    /** 模拟依赖对象 */
    /** 交易订单DAO */
    @Mock
    private TradeOrderDAO tradeOrderDAO;
    /** 执行器服务 */
    @Spy
    private ExecutorService executorService = Executors.newFixedThreadPool(10);
    /** 定义测试对象 */
    /** 交易订单服务 */
    @InjectMocks
    private TradeOrderService tradeOrderService;
    /**
     * 测试: 获取交易订单列表-正常
     */
    @Test
    public void testGetTradeOrdersWithNormal() {
        // 模拟依赖方法
        // 模拟依赖方法: tradeOrderDAO.get
        String path = RESOURCE_PATH + "testGetTradeOrdersWithNormal/";
        String text = ResourceHelper.getResourceAsString(getClass(), path + "tradeOrderMap.json");
        Map<Long, TradeOrderDO> tradeOrderMap = JSON.parseObject(text, new TypeReference<Map<Long, TradeOrderDO>>() {});
        Mockito.doAnswer(invocation -> tradeOrderMap.get(invocation.getArgument(0)))
            .when(tradeOrderDAO).get(Mockito.anyLong());
        // 调用测试方法
        text = ResourceHelper.getResourceAsString(getClass(), path + "orderIdList.json");
        List<Long> orderIdList = JSON.parseArray(text, Long.class);
        List<TradeOrderVO> tradeOrderList = tradeOrderService.getTradeOrders(orderIdList);
        text = ResourceHelper.getResourceAsString(getClass(), path + "tradeOrderList.json");
        Assert.assertEquals("交易订单列表不一致", text, JSON.toJSONString(tradeOrderList));
        // 验证依赖方法
        // 验证依赖方法: tradeOrderDAO.get
        ArgumentCaptor<Long> orderIdCaptor = ArgumentCaptor.forClass(Long.class);
        Mockito.verify(tradeOrderDAO, Mockito.atLeastOnce()).get(orderIdCaptor.capture());
        Assert.assertEquals("订单标识列表不一致", orderIdList, orderIdCaptor.getAllValues());
    }
}



《Java单元测试实战》——案例集锦:Java单元测试典型案例集锦(11) https://developer.aliyun.com/article/1232048?groupCode=java

 

相关文章
|
10月前
|
自然语言处理 前端开发 Java
JBoltAI 框架完整实操案例 在 Java 生态中快速构建大模型应用全流程实战指南
本案例基于JBoltAI框架,展示如何快速构建Java生态中的大模型应用——智能客服系统。系统面向电商平台,具备自动回答常见问题、意图识别、多轮对话理解及复杂问题转接人工等功能。采用Spring Boot+JBoltAI架构,集成向量数据库与大模型(如文心一言或通义千问)。内容涵盖需求分析、环境搭建、代码实现(知识库管理、核心服务、REST API)、前端界面开发及部署测试全流程,助你高效掌握大模型应用开发。
917 5
|
8月前
|
算法 IDE Java
Java 项目实战之实际代码实现与测试调试全过程详解
本文详细讲解了Java项目的实战开发流程,涵盖项目创建、代码实现(如计算器与汉诺塔问题)、单元测试(使用JUnit)及调试技巧(如断点调试与异常排查),帮助开发者掌握从编码到测试调试的完整技能,提升Java开发实战能力。
759 0
|
9月前
|
安全 Java 测试技术
Java 项目实战中现代技术栈下代码实现与测试调试的完整流程
本文介绍基于Java 17和Spring技术栈的现代化项目开发实践。项目采用Gradle构建工具,实现模块化DDD分层架构,结合Spring WebFlux开发响应式API,并应用Record、Sealed Class等新特性。测试策略涵盖JUnit单元测试和Testcontainers集成测试,通过JFR和OpenTelemetry实现性能监控。部署阶段采用Docker容器化和Kubernetes编排,同时展示异步处理和反应式编程的性能优化。整套方案体现了现代Java开发的最佳实践,包括代码实现、测试调试
290 0
|
9月前
|
安全 Java API
Java 集合高级应用与实战技巧之高效运用方法及实战案例解析
本课程深入讲解Java集合的高级应用与实战技巧,涵盖Stream API、并行处理、Optional类、现代化Map操作、不可变集合、异步处理及高级排序等核心内容,结合丰富示例,助你掌握Java集合的高效运用,提升代码质量与开发效率。
355 0
|
10月前
|
缓存 算法 NoSQL
校招 Java 面试高频常见知识点深度解析与实战案例详细分享
《2025校招Java面试核心指南》总结了Java技术栈的最新考点,涵盖基础语法、并发编程和云原生技术三大维度: 现代Java特性:重点解析Java 17密封类、Record类型及响应式Stream API,通过电商案例演示函数式数据处理 并发革命:对比传统线程池与Java 21虚拟线程,详解Reactor模式在秒杀系统中的应用及背压机制 云原生实践:提供Spring Boot容器化部署方案,分析Spring WebFlux响应式编程和Redis Cluster缓存策略。
283 0
|
10月前
|
人工智能 Java API
Java 生态大模型应用开发全流程实战案例与技术路径终极对决
在Java生态中开发大模型应用,Spring AI、LangChain4j和JBoltAI是三大主流框架。本文从架构设计、核心功能、开发体验、性能扩展性、生态社区等维度对比三者特点,并结合实例分析选型建议。Spring AI适合已有Spring技术栈团队,LangChain4j灵活性强适用于学术研究,JBoltAI提供开箱即用的企业级解决方案,助力传统系统快速AI化改造。开发者可根据业务场景和技术背景选择最适合的框架。
2232 2
|
9月前
|
人工智能 Java 测试技术
Java or Python?测试开发工程师如何选择合适的编程语言?
测试工程师如何选择编程语言?Java 还是 Python?多位资深专家分享建议:Python 入门简单、开发效率高,适合新手及自动化测试;Java 生态成熟,适合大型项目和平台开发。建议结合公司技术栈、个人基础及发展方向选择。长远来看,两者兼通更佳,同时关注 Go 等新兴语言。快速学习与实践才是关键。
|
9月前
|
安全 JavaScript Java
java Web 项目完整案例实操指南包含从搭建到部署的详细步骤及热门长尾关键词解析的实操指南
本项目为一个完整的JavaWeb应用案例,采用Spring Boot 3、Vue 3、MySQL、Redis等最新技术栈,涵盖前后端分离架构设计、RESTful API开发、JWT安全认证、Docker容器化部署等内容,适合掌握企业级Web项目全流程开发与部署。
741 0
|
数据可视化 前端开发 测试技术
接口测试新选择:Postman替代方案全解析
在软件开发中,接口测试工具至关重要。Postman长期占据主导地位,但随着国产工具的崛起,越来越多开发者转向更适合中国市场的替代方案——Apifox。它不仅支持中英文切换、完全免费不限人数,还具备强大的可视化操作、自动生成文档和API调试功能,极大简化了开发流程。
|
10月前
|
Java 测试技术 容器
Jmeter工具使用:HTTP接口性能测试实战
希望这篇文章能够帮助你初步理解如何使用JMeter进行HTTP接口性能测试,有兴趣的话,你可以研究更多关于JMeter的内容。记住,只有理解并掌握了这些工具,你才能充分利用它们发挥其应有的价值。+
1386 23