System.currentTimeMillis()在Kotlin Springboot应用程序中返回0L



我正在开发一个由Java和Kotlin混合编写的Springboot应用程序。我们有休息控制器、服务和数据库存储库,它们都需要知道墙上的时钟时间。

我们可以直接调用System.currentTimeMillis(),但我们的一些单元测试需要模拟当前时间来测试与时间相关的行为,所以我们创建了这个接口:

import java.time.OffsetDateTime;
public interface TimeService {
long currentTimeMillis();
OffsetDateTime nowUtc();
}

这个接口的实现:

import java.time.OffsetDateTime;
import java.time.ZoneOffset;
public class SystemTimeService implements TimeService {
@Override
public long currentTimeMillis() {
return System.currentTimeMillis();
}
@Override
public OffsetDateTime nowUtc() {
return OffsetDateTime.now(ZoneOffset.UTC);
}
}

以及这个bean,它告诉Springboot如何创建接口的实例:

@Bean
public TimeService timeService() {
return new SystemTimeService();
}

现在,我们的代码可以使用Springboot注入并使用TimeService的实例,如下所示:

@Service
class SomeService(
private val timeService: TimeService
) {
fun doSomethingWithTime() {
val now = timeService.currentTimeMillis()
// do something with now
}
}

问题是,有时在运行单元测试时,timeService.currentTimeMillis()会返回0L,这应该是不可能的。

这似乎只在我们运行整个测试套件时发生,而在调试时发生的频率较低,所以我认为这是一个竞争条件,但我很难追踪它。如果我用对System.currentTimeMillis()的直接调用来代替对timeService.currentTimeMillis()的使用,我就无法重现这个问题。

Springboot是否有可能破坏了这个bean的生命周期,以至于mock在我们不打算使用的地方被重新使用?注入的bean会因为Kotlin处理线程和异步执行suspended函数的方式而超出作用域吗?我在JVM中发现错误了吗?

任何想法或建议都将不胜感激。

我能够添加一些日志,在我没想到的时候确认我的ApplicationContext包含一个mock。我发现了一个使用@MockBean(TimeService::class)创建mock的测试,但它本身并没有清理。我在该测试中添加了一个@DirtiesContext注释,它似乎解决了mock问题。

相关内容

  • 没有找到相关文章

最新更新