• spring 单元测试为 logback 添加环境变量


    场景描述

    spring 项目中配置了 logback 收集日志,同时使用 @SpringBootTest 做单元测试。此时就报错了,文件找不见。

    ERROR in ch.qos.logback.core.rolling.RollingFileAppender[file] - Failed to create parent directories for [/home/zhu/app/logs/2022-09-07.log]
    ERROR in ch.qos.logback.core.rolling.RollingFileAppender[file] - openFile(null,true) call failed. java.io.FileNotFoundException: /home/zhu/app/logs/2022-09-07.log (No such file or directory)


    原因

    logback-spring.xml 文件中这么写的,bosc.rec.logSavePath 指定保存日志文件,可以在 application.yml 指定。

    
    <configuration scan="false" packagingData="true">
        <springProperty scope="context" name="LOG_HOME" source="bosc.rec.logSavePath" />
      	
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    # application.yml
    bosc:
      rec:
        logSavePath: ${LOG_SAVE_PATH:/home/zhu/app/logs}
    
    • 1
    • 2
    • 3
    • 4

    单元测试启动时先加载 logback 的配置,再执行测试 case。日志文件找不到,就会抛出上面的异常。而且使用 @Before, @BeforeAll 或者 static 方法,在内部 System.setProperty() 设置环境变量的方式也都不能解决问题。因为这些方法的执行都晚于 logback 配置的加载。


    解决办法

    直接上代码。

    public class PropertyExtension implements BeforeAllCallback {
      @Override
      public void beforeAll(ExtensionContext context) {
        System.setProperty("LOG_SAVE_PATH", "/Users/mac/Downloads/bosc/logs");
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    @ExtendWith(PropertyExtension.class)
    @SpringBootTest(classes = JobManageApplication.class)
    class ScenePipelineRepositoryImplTest {
    
      @Autowired
      ScenePipelineRepository repository;
    
      @Test
      public void save_ScenePipeline_succeed() {
    			// 内容省略
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    啰嗦几句

    之所以抛出异常是因为使用 @SpringBootTest 做单元测试,这个注解会在执行测试 case 时会启动整个 spring 服务,所以会执行 spring 的初始化过程,加载一大堆的东西,从而包括了 logback 这玩意。

    但这样使用是不合理的:

    原因一:单测只测一个功能点,有必要把整个服务都启动吗?又不是做集成测试。

    原因二:假如服务中有定时任务 或者 向其他服务发请求的功能,那么这个任务也会运行,这是单测不想看到的现象。

    @SpringBootTest 适合做集成测试,测试成功后采用 @ignore 将测试类注解掉。

    spring 三层结构,每层都有单测,每层测试的目的和方式都不一样。

    曾今写过的一篇单测博客

    要让团队成员都遵守一些规矩还是有些挑战的。

  • 相关阅读:
    day51
    PMP是什么?
    免杀对抗-C#+go语言-混淆+防反编译+分离
    第137篇 荷兰拍卖
    BBR 降本增效
    设计模式与应用:备忘录模式
    查找或替换excel换行符ctrl+j和word中的换行符^p,^l
    JavaScript中的原型和原型链
    什么是MVCC?
    Nexus3搭建以及使用
  • 原文地址:https://blog.csdn.net/yy_diego/article/details/126743074