检查枚举类的唯一属性

时间:2018-11-19 16:49:55

标签: java generics junit enums

我的项目中有几个枚举类。为了维护持久性,我们不依赖内部ID,因为内部ID随枚举值的顺序而变化(例如,当稍后在两者之间的某个位置添加新枚举时)。而是将(通常是数字的)id属性分配给每个值。

但这打开了另一个错误可能性:同一个ID可以分配两次。因此,我创建了一个JUnit测试,该测试检查所有值的ID是否重复。而且我想使该测试通用,以避免为每个新的枚举类复制粘贴。带有枚举类和用于持续性的getter并运行测试的东西,例如:

(new JUnitEnumTester(OneEnum.class, getId)).runTest()
(new JUnitEnumTester(TwoEnum.class, getName)).runTest()

到目前为止,我要做的是对单个枚举类的测试:

package com.xyz.enums;

import static org.junit.Assert.*;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;

public class OneTest {

    @Test
    // Testing enum IDs
    public void testUniqueId_WithMap() {
        Map<Integer,String> idMap = new HashMap<Integer,String>();
        String msg = "";
        for (One elem : One.values()) {
            Integer enumId = new Integer(elem.getId());
            if (idMap.containsKey(enumId)) {
                msg += "\nDuplicate ID found: '" + enumId.toString() +
                        "' for enum: " + idMap.get(enumId) + ", " + elem.name();
            }
            else {
                idMap.put(enumId, elem.name());
            }
        }

        if (msg.length() > 0) {
            fail(msg);
        }
    }
}

问题是,如何概括这种方法?

首先,我要使用静态方法,但无法弄清楚如何引用该方法用作吸气剂。

public class JUnitTester {
    static public void runTest(Class cls, ? method) {
        :
    }
}

我认为这还是行不通的,所以我现在正在使用泛型。尽管它似乎更面向对象,但仍然不能滚动。

public class JunitEnumTester <? extends Enum> {

    public void runTest() {
        Map<Integer,String> idMap = new HashMap<Integer,String>();
        String msg = "";
        for (Enum elem : Enum.values()) {
            Integer enumId = new Integer(elem.getId());
            if (idMap.containsKey(enumId)) {
                msg += "\nDuplicate ID: '" + enumId.toString() +
                        "' for " + idMap.get(enumId) + ", " + elem.name();
            }
            else {
                idMap.put(enumId, elem.name());
            }
        }

        if (msg.length() > 0) {
            fail(msg);
        }
    }
}

有什么提示或路线指示吗?

1 个答案:

答案 0 :(得分:0)

要重用您的方法,我们需要对其进行概括。我们需要枚举值,我们可以调用枚举值来获取相应的ID。这两个依赖项应作为参数传递。

枚举类型T的枚举值可以作为数组T[]传递。要获取枚举的ID,我们可以使用Function<T, ID> idExtractor,它采用类型为T的枚举值,并返回其类型为ID的ID。

方法如下:

  public static <T extends Enum<T>, ID> void testUniqueIds(T[] enumValues, Function<T, ID> idExtractor) {
    String msg = "";

    Map<ID, T> enumsById = new HashMap<>();
    for (T enumValue : enumValues) {
      ID id = idExtractor.apply(enumValue);
      if (enumsById.containsKey(id)) {
        msg += "\nDuplicate ID found: '" + id.toString() + "' for enum: " + enumsById.get(id) + ", " + enumValue.name();
      } else {
        enumsById.put(id, enumValue);
      }
    }

    if (!msg.isEmpty()) {
      fail(msg);
    }
  }

让我们看一个小例子:

enum ABC {
    A('a'), B('b'), C('c');

    private char letter;

    private ABC(char letter) {
        this.letter = letter;
    }

    public char getLetter() {
       return letter;
    }
}

对应的测试方法:

@Test
void testABC() {
  JunitEnumTester.testUniqueIds(ABC.values(), ABC::getLetter);
}

要传递枚举值,我们使用在每个枚举上定义的方法values()。为了传递id提取器函数,我们使用一个方法引用,该引用使调用简短。

如果我们运行测试,它将为绿色。但是,如果我们使用字母C初始化枚举常量'a',则测试将失败。