如何使用Spock在LocalDate中模拟静态方法?

问题描述

我想模拟LocalDate.Now()每次返回相同的日期。

为此,我尝试了两种不同的选择:

第一名:LocalDate.Now() >> LocalDate.of(2020,05,07)

第二:

def today = GroovyMock(LocalDate) {
                  getYear() >> 2020
                  getMonth() >> Month.APRIL
                  getDayOfMonth() >> 24
                  getDayOfWeek() >> DayOfWeek.FRIDAY
                }
    LocalDate.Now(timeZone) >> today

但这对我没有帮助,LocalDate.Now()仍在调用代码时返回当前日期。每次返回模拟日期时如何实现LocalDate.Now()?

解决方法

不要。正是出于这个原因,Clock类的存在正是出于 的原因。在被测类中,添加带有setter的属性:

private Clock clock = Clock.systemUTC();

并使用

LocalDate.now(clock)

在您的测试用例中,将默认的“真实时钟”替换为测试时钟:

subject.clock = Clock.fixed(specificInstant,UTC)
,

在Spock中无法使用内置工具来模拟Java类的静态方法。如果您确实想要-我同意您不赞成chrylis-您将需要使用其他工具,例如PowerMock或Sarek(我自己的一个宠物项目,仍未正式发布,但可在GitHub上使用)。

背景:顾名思义,Groovy模拟仅适用于Groovy类。将它们与Java类一起使用会使它们的行为类似于常规的Spock模拟,即,对静态方法进行存根无效。 here中对此进行了记录:

什么时候应该比常规的模仿更喜欢Groovy的模仿?当规范下的代码用Groovy 编写并且需要某些独特的Groovy模拟功能时,应使用Groovy模拟。 从Java代码调用时,Groovy模拟将表现得像普通模拟一样。请注意,仅因为规范和/或模拟类型下的代码是用Groovy编写的,所以不必使用Groovy模拟。除非您有具体的理由使用Groovy模拟,否则请选择常规模拟。