【发布时间】:2025-12-15 02:40:01
【问题描述】:
我有一个尝试用 Spock 测试的 Java 类。 Java 类包含一个内部枚举:
import static java.util.Calendar.*;
import java.util.*;
public class FederalHolidays {
public enum Observance {
NEW_YEARS_DAY(JANUARY, 1),
BIRTHDAY_OF_MARTIN_LUTHER_KING_JR(JANUARY, MONDAY, 3),
WASHINGTONS_BIRTHDAY(FEBRUARY, MONDAY, 3),
MEMORIAL_DAY(MAY, MONDAY, -1),
INDEPENDENCE_DAY(JULY, 4),
LABOR_DAY(SEPTEMBER, MONDAY, 1),
COLUMBUS_DAY(OCTOBER, MONDAY, 2),
VETERANS_DAY(NOVEMBER, 11),
THANKSGIVING_DAY(NOVEMBER, THURSDAY, 4),
CHIRSTMAS_DAY(DECEMBER, 25);
private final int month;
private final int dayOfMonth;
private final int dayOfWeek;
private final int weekOfMonth;
private static final int NA = 0;
private Observance(int month, int dayOfMonth) {
this.month = month;
this.dayOfMonth = dayOfMonth;
this.dayOfWeek = NA;
this.weekOfMonth = NA;
}
private Observance(int month, int dayOfWeek, int weekOfMonth) {
this.month = month;
this.dayOfMonth = NA;
this.dayOfWeek = dayOfWeek;
this.weekOfMonth = weekOfMonth;
}
boolean isFixedDate() {
return dayOfMonth != NA;
}
}
public Date dateOf(Observance observance, int year) {
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST"), Locale.ENGLISH);
cal.set(YEAR, year);
cal.set(MONTH, observance.month);
cal.clear(HOUR);
if (observance.isFixedDate()) {
cal.set(DAY_OF_MONTH, observance.dayOfMonth);
} else {
setNthDayOfWeek(cal, observance.dayOfWeek, observance.weekOfMonth);
}
adjustForWeekendsIfNecessary(cal);
return cal.getTime();
}
private void setNthDayOfWeek(Calendar cal, int dayOfWeek, int n) {
int week = 0;
int lastDay = cal.getActualMaximum(DAY_OF_MONTH);
int startDay = n > 0 ? 1 : lastDay;
int endDay = n > 0 ? lastDay : 1;
int incrementValue = n > 0 ? 1 : -1;
for (int day = startDay; day != endDay; day += incrementValue) {
cal.set(DAY_OF_MONTH, day);
if (cal.get(DAY_OF_WEEK) == dayOfWeek) {
week += incrementValue;
if (week == n) {
return;
}
}
}
}
private void adjustForWeekendsIfNecessary(Calendar cal) {
int dayOfWeek = cal.get(DAY_OF_WEEK);
cal.add(DAY_OF_MONTH, dayOfWeek == SATURDAY ? -1 : dayOfWeek == SUNDAY ? 1 : 0);
}
}
我的 Spock 测试规范如下所示:
class FederalHolidaysSpec extends Specification {
@Shared
def federalHolidays = new FederalHolidays()
def "holidays are correctly calculated"() {
expect:
federalHolidays.dateOf(observance, year).format('yyyy/MM/dd') == date
where:
observance | year | date
NEW_YEARS_DAY | 2011 | '2010/12/31'
BIRTHDAY_OF_MARTIN_LUTHER_KING_JR | 2011 | '2011/01/17'
WASHINGTONS_BIRTHDAY | 2011 | '2011/02/21'
MEMORIAL_DAY | 2011 | '2011/05/30'
INDEPENDENCE_DAY | 2011 | '2011/07/04'
LABOR_DAY | 2011 | '2011/09/05'
COLUMBUS_DAY | 2011 | '2011/10/10'
VETERANS_DAY | 2011 | '2011/11/11'
THANKSGIVING_DAY | 2011 | '2011/11/24'
CHIRSTMAS_DAY | 2011 | '2011/12/26'
}
}
当我运行 Spock 时,我得到了 10 个测试错误,表格的每一行都有一个。每个错误都是相同的:
groovy.lang.MissingPropertyException: No such property: Observance for class: bdkosher.FederalHolidaysSpec
at bdkosher.FederalHolidaysSpec.$spock_initializeFields(FederalHolidaysSpec.groovy)
(我正在使用 Spock 0.7-groovy-2.0、groovy-all 2.2.2(非 indy)和 Java 1.7.0_45。)
Spock 为什么要在我的 FederalHolidaysSpec 类中寻找名为 Observance 的属性? 我最初怀疑这个问题与内部枚举/静态导入有关,尽管将我的 Spock 测试更改为使用完全限定的枚举值(例如 bdkosher.FederalHolidays.Observance.CHRISTMAS_DAY)并没有产生任何影响。
编辑:Java 文件实现已更正,因此它通过了测试;测试文件中的错别字已更正。
【问题讨论】:
-
enum不是也必须公开吗? -
是的,很好(我还没有尝试在它的包之外使用 API)。但即使我在上面加上
public修饰符,我仍然会得到相同的测试错误。 -
@BDKosher 我检查了你的代码。这个对我有用。我的设置:groovy 2.2.1,spock 0.7-groovy-2.0。除了多个拼写错误和 2 个错误计算的日期外,一切运行顺利。