如何为定时清理文件的StandardIntegrationFlow编写功能测试?
测试方案验证与Minio文件时间设置实现
测试方案合理性
你的测试思路完全合理,精准覆盖了核心业务场景:
- 验证旧文件被删除、新文件保留的核心逻辑,完全匹配需求预期
- 通过手动触发
SourcePollingChannelAdapter替代等待cron表达式,大幅提升测试效率,避免不必要的时间等待 - 测试前验证文件存在、测试后验证结果的流程,保证了测试的闭环性
需要注意的细节:
- 测试时建议临时调整清理阈值(比如将配置中的清理天数改为1分钟或更短),避免测试依赖真实的10天时间窗口
- 确保获取
SourcePollingChannelAdapter时使用正确的ID(你的代码中是oldReceiptsCleanerPoller),可通过ApplicationContext.getBean()直接获取
在Minio中创建指定修改时间的文件
Minio支持通过上传时设置属性或HTTP头指定文件的Last-Modified时间,结合Spring Integration的SFTP模板或Minio原生SDK都可以实现:
方法1:通过Spring Integration SFTP模板设置
利用RecursiveSftpRemoteFileTemplate的execute方法,上传文件后修改其属性:
import org.springframework.integration.sftp.session.RecursiveSftpRemoteFileTemplate import java.io.ByteArrayInputStream // 假设已注入receiptSftpRemoteFileTemplate private void createFileWithModifiedTime(String remotePath, long modifiedTimestamp) { receiptSftpRemoteFileTemplate.execute(session -> { // 上传文件内容 session.write(new ByteArrayInputStream("test content".getBytes()), remotePath) // 设置文件修改时间 def attrs = new HashMap<String, Object>() attrs.put("last-modified", modifiedTimestamp) session.getClient().setStat(remotePath, attrs) return null }) }
方法2:使用Minio原生SDK设置
如果直接操作Minio存储,可通过PutObjectArgs的headers指定修改时间:
import io.minio.PutObjectArgs import io.minio.MinioClient import java.time.ZonedDateTime import java.time.format.DateTimeFormatter // 初始化Minio客户端 def minioClient = MinioClient.builder() .endpoint("http://your-minio-endpoint") .credentials("access-key", "secret-key") .build() // 生成11天前的时间格式(符合HTTP头要求) def oldFileTime = ZonedDateTime.now().minusDays(11) def dateHeader = oldFileTime.format(DateTimeFormatter.RFC_1123_DATE_TIME) // 上传旧文件并指定修改时间 minioClient.putObject( PutObjectArgs.builder() .bucket("test-bucket") .object("old-receipt.txt") .stream(new ByteArrayInputStream("old content".getBytes()), -1, 10485760) .headers(Map.of("Last-Modified", dateHeader)) .build() )
Spock测试完整示例
import org.springframework.beans.factory.annotation.Autowired import org.springframework.context.ApplicationContext import org.springframework.integration.endpoint.SourcePollingChannelAdapter import org.springframework.integration.sftp.session.RecursiveSftpRemoteFileTemplate import spock.lang.Specification import java.time.Duration class OldReceiptsCleanerSpec extends Specification { @Autowired private RecursiveSftpRemoteFileTemplate receiptSftpRemoteFileTemplate @Autowired private ApplicationContext applicationContext @Autowired private TestProperties testProperties // 自定义测试配置类,覆盖清理阈值 def setup() { // 测试时临时设置清理阈值为1分钟 testProperties.setRetentionDays(0) testProperties.setSftpPath("/test-receipts") } def "test old receipts are cleaned up while new ones remain"() { given: "准备两个测试文件:一个超过清理阈值,一个未超过" def remoteDir = testProperties.getSftpPath() def oldFilePath = "${remoteDir}/old-receipt.txt" def newFilePath = "${remoteDir}/new-receipt.txt" // 创建旧文件(修改时间为2分钟前) createFileWithModifiedTime(oldFilePath, System.currentTimeMillis() - Duration.ofMinutes(2).toMillis()) // 创建新文件(修改时间为30秒前) createFileWithModifiedTime(newFilePath, System.currentTimeMillis() - Duration.ofSeconds(30).toMillis()) expect: "初始状态下两个文件都存在" receiptSftpRemoteFileTemplate.exists(oldFilePath) receiptSftpRemoteFileTemplate.exists(newFilePath) when: "手动触发清理流程" SourcePollingChannelAdapter poller = applicationContext.getBean("oldReceiptsCleanerPoller", SourcePollingChannelAdapter) poller.start() sleep(1000) // 等待处理完成,可根据实际情况调整等待时间 poller.stop() then: "旧文件被删除,新文件保留" !receiptSftpRemoteFileTemplate.exists(oldFilePath) receiptSftpRemoteFileTemplate.exists(newFilePath) } private void createFileWithModifiedTime(String remotePath, long modifiedTimestamp) { receiptSftpRemoteFileTemplate.execute(session -> { session.write(new ByteArrayInputStream("test content".getBytes()), remotePath) def attrs = new HashMap<String, Object>() attrs.put("last-modified", modifiedTimestamp) session.getClient().setStat(remotePath, attrs) return null }) } }
内容的提问来源于stack exchange,提问作者Vasilis Iak
相关产品推荐
相关产品推荐

