【问题标题】:Using Java 8 is there a way to validate/assert that a constant is a compile-time constant?使用 Java 8 有没有办法验证/断言常量是编译时常量?
【发布时间】:2019-05-09 17:08:18
【问题描述】:

我想要一个 JUnit 测试来验证特定常量是编译时常量。 我该怎么做呢?

我找到了适用于 Scala 的解决方案,但我希望使用纯 Java。
Is there a way to test at compile-time that a constant is a compile-time constant?

根本原因:

The value for annotation attribute ApiModelProperty.allowableValues must be a constant expression

我在单元测试中想要什么:
    validateCompileTimeConstant(SomeClass.CONSTANT_VALUE, "Message Here!!");
用法
    @ApiModelProperty(name = "name", required = true, value = "Name", allowableValues=SomeClass.API_ALLOWABLE_VALUES, notes=SomeClass.API_NOTES)
    private String name;
某类
public enum SomeClass {
    BOB(4,  "Bob"),//
    TED(9,  "Ted"),//
    NED(13, "Ned");

    public static final String API_ALLOWABLE_VALUES = "4,9,13,16,21,26,27,170";
    public static final String API_NOTES = "4 - Bob\n" +
                                           "9 - Ted\n" +
                                           "13 - Ned";

    public int code;
    public String desc;

    private ContentCategoryCode(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public static final String apiAllowableValues() {
        StringBuilder b = new StringBuilder();
        for (ContentCategoryCode catCode : values()) {
            b.append(catCode.code);
            b.append(',');
        }
        b.setLength(b.length()-1);
        return b.toString();
    }

    public static final String apiNotes() {
        StringBuilder b = new StringBuilder();
        for (ContentCategoryCode catCode : values()) {
            b.append(catCode.code).append(" - ").append(catCode.desc);
            b.append('\n');
        }
        b.setLength(b.length()-1);
        return b.toString();
    }
}

【问题讨论】:

  • 这不是你要在运行时测试的东西。从本质上讲,编译时常量的滥用会在编译时失败,编译器会检测到。
  • 你不应该编写依赖于这种或另一种方式的代码。
  • 我只能支持@Savior。当编译器已经告诉你有错误时,为什么还要运行单元测试?
  • 如果有人试图生成常量的值,我可以记录修复。本质上,我想要单元测试类中的“为什么编译失败”。

标签: java java-8


【解决方案1】:

Error Prone 项目有一个 @CompileTimeConstant 注释,可用于强制执行此操作。

这不是使用 JUnit 运行的测试,而是在编译时强制执行此(和其他错误模式)的编译器插件。

这里是文档:https://errorprone.info/bugpattern/CompileTimeConstant

【讨论】:

    【解决方案2】:

    我最终创建了自己的注释,因为与使用 Error Prone 相比,它需要的设置更少。

    注解类:

    @Target(ElementType.METHOD)
    public @interface TestCompileTimeConstant {
        public String key() default "";
    }
    

    JUnit 测试:

    public class SomeClassTest {
    
        @Test
        public void test() {
            assertEquals(SomeClass.API_ALLOWABLE_VALUES, SomeClass.apiAllowableValues());
            assertEquals(SomeClass.API_NOTES, SomeClass.apiNotes());
        }
    
        @Test
        @TestCompileTimeConstant(key=SomeClass.API_ALLOWABLE_VALUES)
        public void testIsCompileTimeConstant1() {
            //Pass - If this doesn't compile, you need to make sure API_ALLOWABLE_VALUES doesn't call any methods.
        }
    
        @Test
        @TestCompileTimeConstant(key=SomeClass.API_NOTES)
        public void testIsCompileTimeConstant2() {
            //Pass - If this doesn't compile, you need to make sure API_NOTES doesn't call any methods. 
        }
    }
    
    

    【讨论】:

    • 这里不需要RetentionPolicy.RUNTIME。否则,这似乎是一个合理的解决方案。
    猜你喜欢
    • 2014-02-10
    • 2010-09-11
    • 1970-01-01
    • 2018-11-26
    • 2010-09-06
    • 2013-08-31
    • 1970-01-01
    • 1970-01-01
    • 2018-10-23
    相关资源
    最近更新 更多