java - 使用 cron 进行单元测试 @Sheduled
问题描述
我需要测试是否在每个午夜执行以下计划方法:
public class CacheService {
/** Evicts token from the cache at midnight */
@Scheduled(cron = "0 0 0 * * *", zone = "Europe/London")
@CacheEvict(value = CacheConfig.AUTH_TOKEN, allEntries = true)
public void clearCacheAtMidnight() {
log.info("Scheduled cache clean at: " + Instant.now());
}
}
我正在使用以下单元测试:
@SpringBootTest
class CacheServiceTest {
@SpyBean private CacheService cacheService;
@Test
void shouldClearCacheAtMidnight() {
Instant.now(Clock.fixed(Instant.parse("2020-01-01T00:00:00Z"), ZoneId.of("Europe/London")));
await()
.atMost(Duration.ofMinutes(1))
.untilAsserted(() -> verify(cacheService, atLeast(1)).clearCacheAtMidnight());
}
}
但不是快乐。如果我从 cron 更改为 fixrate,它会完美运行。我有一种感觉,我没有正确覆盖系统时钟,或者我没有正确使用设置的间隔。
有什么线索吗?
解决方案
Spring 内部使用CronSequenceGenerator
解析 cron 表达式以找出下一个触发时间。如果要测试是否正确设置了 cron 表达式,可以参考他们的测试用例并编写自己的测试用例,例如:
@Test
public void myTest() {
CronSequenceGenerator cronSequenceGenerator = new CronSequenceGenerator("0 0 0 * * *",TimeZone.getTimeZone("Europe/London"));
ZonedDateTime date = LocalDateTime.of(2020, 6, 1, 9, 52, 0).atZone(ZoneId.of("Europe/London"));
ZonedDateTime expected = LocalDateTime.of(2020, 6, 2, 0, 0, 0).atZone(ZoneId.of("Europe/London"));
assertThat(cronSequenceGenerator.next(Date.from(date.toInstant()))).isEqualTo(Date.from(expected.toInstant()));
}
我同意一些测试人员在测试框架时不会建议这样做,但我肯定会包含它,因为它很容易编写,至少我会更有信心我的 cron 表达式配置正确,尤其是在某些时候我们需要设置一些重要的 cron 表达式。
推荐阅读
- c# - 有没有办法在异步操作执行之前更改它的优先级?
- python - Cython 的速度没有明显提高:如何在 Cython 中处理 NumPy 广播?
- python - 比较 NumPy 数组的相似性
- ios - 无法为简单的 Objective-C 对象创建属性
- ios - 如何在 SwiftUI 中将 ScrollView 布局方向从右到左?
- cakephp - 如何在 HABTM 关系中实现“相关帖子”?
- eclipse-clp - 是否有很好的资源来查找 ECLiPSe 的常见问题?
- docker - AKS 外部负载均衡器未与 PODS 通信
- python - 定义时如何修复“名称未定义”?
- python-3.x - 在 pytest.ini 中设置 pytest-benchmark 配置