Java 斯波克认为被测试类的内部枚举应该是Spec的属性

Java 斯波克认为被测试类的内部枚举应该是Spec的属性,java,groovy,enums,spock,Java,Groovy,Enums,Spock,我有一个Java类,我正试图用Spock测试它。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,

我有一个Java类,我正试图用Spock测试它。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.045。)

为什么斯波克要在我的FederalHolidaysSpec类中查找名为Observation的属性? 我最初怀疑该问题与内部枚举/静态导入有关,但将我的Spock测试更改为使用完全限定的枚举值(例如bdkosher.FederalHolidays.Observation.CHRISTMAS_DAY)并没有什么区别


编辑:Java文件实现已更正,以便通过测试;测试文件中的输入错误已更正。

请确保源代码和测试用例的软件包都正确。如果java类和测试类都在同一个包中,那么下面的方法对我来说是可行的

package bdkosher

import spock.lang.Shared
import spock.lang.Specification
//import bdkosher.FederalHolidays.Observance //Do not need
import static bdkosher.FederalHolidays.Observance.*

class FederalHolidaysSpec extends Specification { .. }

我在没有默认包名的情况下测试了
com.example
和Grails应用程序,尽管spock版本是相同的。

在听说@elems'和@dmahaptro的成功后,我开始从我的项目结构中剥离一些东西,并减少POM中的依赖项

在完全删除了未使用的
src/test/java
src/main/groovy
目录后,我注意到IDE中的
FederalHolidaysSpec.groovy
源文件恢复为旧版本(我不确定是否应该为此责备
gmavenplus插件
或NetBeans——我怀疑是后者,因为我一直在使用
mvn clean test
进行测试)。无论如何,这个旧版本包含一个额外的字段:

class FederalHolidaysSpec extends Specification {

    def data = [(Observance.NEW_YEARS_DAY) : ['2011/12/31']]
此字段导致了测试错误。即使使用
导入bdkosher.FederalHolidays.observation
,Groovy显然认为映射键是属性引用,而不是
枚举
引用


无论如何,现在我可以修复打字错误和合法的测试失败。谢谢你的帮助。

枚举是否也必须公开?是的,很好(我还没有尝试在其包之外使用API)。但是,即使我在上面添加了
public
修饰符,我仍然会得到相同的测试错误。@BDKosher我检查了你的代码。它对我很有效。我的设置:groovy 2.2.1,spock 0.7-groovy-2.0。除了多个输入错误和两个计算错误的日期外,所有这些都运行得很顺利。我不完全确定groovy是否支持导入嵌套类。看起来是这样的y、 使用FQN--
def数据=[(gov.uspto.trademark.tmng.datetime.FederalHolidays.Observation.NEW_YEARS_DAY):['2011/12/31']
——不会导致任何错误。静态导入至少按照我的预期工作。
导入gov.uspto.trademark.tmng.datetime.FederalHolidays
(FederalHolidays.Observation.NEW_DAY)
可能也会起作用。是的,这是有效的。如果我导入gov.uspto.trademark.tmng.datetime.FederalHolidays.observation并定义一个字段
def newYears=observation.NEW_YEARS\u DAY
,Groovy不会有任何抱怨。它只是在用作地图键时有问题。