场景描述
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
指定。
<?xml version="1.0" encoding="UTF-8"?><configurationscan="false"packagingData="true"><springPropertyscope="context"name="LOG_HOME"source="bosc.rec.logSavePath"/><!-- 中间内容省略了 --></configuration>
# application.ymlbosc:rec:logSavePath: ${LOG_SAVE_PATH:/home/zhu/app/logs}
当单元测试启动时先加载 logback 的配置,再执行测试 case。日志文件找不到,就会抛出上面的异常。而且使用
@Before
,
@BeforeAll
或者
static
方法,在内部
System.setProperty()
设置环境变量的方式也都不能解决问题。因为这些方法的执行都晚于 logback 配置的加载。
解决办法
直接上代码。
publicclassPropertyExtensionimplementsBeforeAllCallback{@OverridepublicvoidbeforeAll(ExtensionContext context){System.setProperty("LOG_SAVE_PATH","/Users/mac/Downloads/bosc/logs");}}
@ExtendWith(PropertyExtension.class)@SpringBootTest(classes =JobManageApplication.class)classScenePipelineRepositoryImplTest{@AutowiredScenePipelineRepository repository;@Testpublicvoidsave_ScenePipeline_succeed(){// 内容省略}
啰嗦几句
之所以抛出异常是因为使用 @SpringBootTest 做单元测试,这个注解会在执行测试 case 时会启动整个 spring 服务,所以会执行 spring 的初始化过程,加载一大堆的东西,从而包括了 logback 这玩意。
但这样使用是不合理的:
原因一:单测只测一个功能点,有必要把整个服务都启动吗?又不是做集成测试。
原因二:假如服务中有定时任务 或者 向其他服务发请求的功能,那么这个任务也会运行,这是单测不想看到的现象。
@SpringBootTest 适合做集成测试,测试成功后采用 @ignore 将测试类注解掉。
spring 三层结构,每层都有单测,每层测试的目的和方式都不一样。
曾今写过的一篇单测博客
要让团队成员都遵守一些规矩还是有些挑战的。
版权归原作者 骑着蜗牛向前跑 所有, 如有侵权,请联系我们删除。