有没有办法断言自上次修订以来枚举没有改变?

时间:2015-09-21 17:32:54

标签: java svn netbeans junit

如果更改了下游项目而没有更改下游项目,则存在一个将导致下游问题的枚举类。不幸的是,仅通过搜索枚举的用法并不容易识别。我们在代码中有一个很大的警告评论说“不要改变它而不改变(下游项目)”,但显然这还不够:墨菲定律坚定。我需要一些其他方法来阻止其他开发人员(或未来的我)破坏事物。

我目前的做法是创建一个单元测试,每当枚举更改时都会抛出错误。因此,更改枚举将导致构建失败,这应引起开发人员的注意。失败消息中包含有关如何安全更新枚举的说明。不幸的是,我没有看到任何编写单元测试的方法,只需将整个枚举复制到测试类中,然后将测试枚举中的每个值与实际枚举进行比较。

有没有办法可以避免在这里重复测试类中的枚举?根据我的描述,您是否认识到我应该遵循最佳做法?

2 个答案:

答案 0 :(得分:2)

如果要验证的只是枚举成员名称和可能的顺序,那么您可以在枚举类型上创建一个静态方法来计算该信息的消化形式。然后,您的单元测试可以调用单个方法来测试枚举是否与预期形式匹配。

例如,

enum Test {
    T1;
    static int computeSignature() {
        StringBuilder sb = new StringBuilder();

        for (Test t : values) {
            sb.append(t.name()).append(';');
        }

        return sb.toString().hashCode();
    }
}

// ...

private final static int EXPECTED_ENUM_SIG = /* some number */;

@Test
public void testEnumSignature() {
    assertEquals("enum Test has been unexpectedly changed", EXPECTED_ENUM_SIG,
            Test.computeSignature());
}

如果您决定不关心枚举顺序,则将名称排序为签名计算的一部分。

答案 1 :(得分:1)

一旦枚举类发布,它就会成为公共API 的一部分,并且大部分都不应该更改。绝对不应该更改枚举常量名称,并且您可能不应该添加任何新常量。

这与在接口上更改方法签名没有多大区别,应该以相同的方式处理。

任何更改都是API中断更改,并且会影响链接到枚举的任何下游程序。

如果你真的必须改变你的枚举,那么你的库应该提高主要版本号并包括解释变化的详细发行说明以及使旧代码兼容必须采取的措施。

不幸的是,枚举的解决方法并不漂亮。

如果你想添加新的枚举,你不能扩展枚举,你不能只扩展旧的枚举类并添加更多的常量。

我建议为枚举中的方法提取interface,让你的枚举类实现新接口并尝试让你的下游软件只使用该接口。然后,您的代码的未来版本可以添加新常量,减少问题。但是初始过渡到界面会很痛苦,但希望只发生一次。

有效Java第2版第34项:“使用接口模拟可扩展枚举”

中详细介绍了这一点。