惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - 陌上花kai

openclaw实践 RooCode结合NacosMCP实践 Dify0.15.1升级1.4.3版本 RooCode结合本地MCP实践 本地密码管理器-Vaultwarden 从业务视角看AI落地:避免技术狂欢,聚焦真实需求 从"我要去山西旅游"看AI智能体的未来之旅:大模型如何重构自动化服务生态 OpenManus+DeepSeek体验 企业知识库落地实践 搭建个人AI知识库-DIFY 搭建个人AI知识库:RAG与本地模型实践指南 分享一个前后端分离后台管理系统 CV高手是怎么炼成的? linux下自建NAS教程 一个9年archlinux重度使用者自述 vim系列-文本操作篇 在日常工作和生活中使用Linux-开篇 ChatGpt怎么玩 如何通过电脑手柄玩安卓手游?
springboot集成测试最小化依赖实践
陌上花kai · 2023-06-16 · via 博客园 - 陌上花kai

目录

  1. 简介
  2. 版本及依赖引入
    1. springboot版本
    2. 项目部分依赖
  3. 直接使用SpringBootTest方式
    1. 代码示例
    2. 场景及优劣
  4. 最小化依赖方案
    1. 代码
    2. 思路及步骤
    3. 最小化依赖方案的优点
  5. 结论

简介

想要代码跑的稳, 集成测试还是必不可少的, 不然出现开发环境正常, 集成环境各种问题就坑爹了。

当前项目对外提供各种rest接口, 通过RestTemplate做接口测试, 同时需要注入一些SpringBean, 如何使用SpringBootTest又不需要启动整个容器?

版本及依赖引入

springboot版本

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.7.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

项目部分依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

直接使用SpringBootTest方式

代码示例

@RunWith(SpringRunner.class)
// 默认启动容器
@SpringBootTest
public class BdgResourceITest {

    @Autowired
    @Qualifier(value = "iTestRestTemplate")
    private RestTemplate restTemplate;

    @Test
    public void testPull() throws URISyntaxException {

        // /pull/{mof_div_code}/{fiscal_year}/{agency_code}
        String url = "/api/pull/340000000/2022/001001";
        final ResponseEntity<ResponseData> exchange = restTemplate.exchange(
                RequestEntity.get(new URI(url)).build(), ResponseData.class);

        Assert.isTrue(exchange.getStatusCode().equals(HttpStatus.OK), "本单位数据获取异常");
    }
}

场景及优劣

优势

如果是测试类中大量引入了依赖, 这种情况下直接启动容器比较方便, 不过集成测试个人感觉从入口访问即可, 这种嵌套比较深的建议使用单元测试

劣势

当前项目中测试代码需要依赖很少, 极端情况下只用restTemplate即可, 根本没必要启动容器, 而且启动容器占用了大量时间

项目中使用了ehcache3.x作为本地缓存, 启动容器后因为文件锁无法测试, 如果单独指定ehcache.xml配置, 又会产生新的垃圾, 所以果断减少依赖

最小化依赖方案

代码

@RunWith(SpringRunner.class)
// 指定class就不启动容器了
@SpringBootTest(classes = BdgResourceITest.class)
@Import(value = {ITestRestTemplateConfigurer.class})
// 激活 main 中resources下的test profile
//@ActiveProfiles("dev")
// 加载测试目录resources下的application.yml文件
//@TestPropertySource(properties = {"spring.config.location=classpath:application.yml"})
public class BdgResourceITest {

    @Autowired
    @Qualifier(value = "iTestRestTemplate")
    private RestTemplate restTemplate;

    @Test
    public void testPull() throws URISyntaxException {

        // /pull/{mof_div_code}/{fiscal_year}/{agency_code}
        String url = "/api/pull/340000000/2022/001001";
        final ResponseEntity<ResponseData> exchange = restTemplate.exchange(
                RequestEntity.get(new URI(url)).build(), ResponseData.class);

        Assert.isTrue(exchange.getStatusCode().equals(HttpStatus.OK), "本单位数据获取异常");
    }
}

思路及步骤

通过指定SpringBootTest的classes, 只启动当前类,如果需要注入其它bean, 则使用@import进行引入

如果import内部的类也也需要引入其它类, 同理根据需要使用@Import注解, 这样产生的代码更加聚合, 所然在当前类可以全部@Import, 但是看着头疼

对于需要引入yml配置信息的,可以配合@EnableConfigurationProperties读取测试目录下的application.yml文件

最小化依赖方案的优点

减少了容器启动时间, 对于当前项目更加符合实际的使用场景, 毕竟第三方使用不可能启动你自己的容器:D

更加优雅的解决了ehcache同时被容器扫描启动, 本地文件锁导致测试无法运行, 实际测试代码根本不需要缓存, 项目服务有就行

测试代码也更加简单优雅, 可以直接提供第三方公司作为接口请求示例代码

结论

如果集成测试的场景类似当前项目情况, 全部测试都从rest接口入手, 建议采用最小容器依赖方案