【问题标题】:Checking for unique attributes of enum classes检查枚举类的唯一属性
【发布时间】:2019-04-22 02:03:08
【问题描述】:

我的项目中有几个枚举类。为了保证持久性,我们不依赖内部 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);
        }
    }
}

问题是,如何推广这种方法?

首先我打算使用静态方法,但不知道如何引用该方法以用作 getter。

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);
        }
    }
}

任何提示或方向去哪里?

【问题讨论】:

  • 枚举是否都共享一个公共基类(即是否有一些继承发生)?
  • @umop-apisdn 目前没有。如果它可以减轻任务,可以添加它。
  • @Walter 我的答案在不更改枚举的情况下有效。
  • @LuCio 正确,我真的学到了很多东西。不过如果有的话,有兴趣看看其他方法。
  • 只是一个提示:如果你得到一个你学到很多东西但不想show if it is helpful的答案,我想知道其他人是否会被激励回答。

标签: java generics junit enums


【解决方案1】:

要重用您的方法,我们需要对其进行泛化。我们需要枚举值和可以调用枚举值的东西来获取相应的 id。这两个依赖项应该作为参数传入。

枚举类型T 的枚举值可以作为数组T[] 传入。要获取枚举的 id,我们可以使用 Function&lt;T, ID&gt; 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 提取器函数,我们使用方法引用,它可以保持调用简短。

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

【讨论】:

  • 经过测试,运行良好。 (会投票,但我还不允许)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-20
  • 2020-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多