有关如何在Java代码中检查非唯一ID的一般信息

时间:2016-10-13 10:45:38

标签: java unit-testing

在一个非常庞大的项目中,有很多ExceptionClasses,其中异常细节被实现为enum

NAME_OF_EXCEPTION_DETAIL(ID, PRIORITY)

e.g:

NO_LICENSE_FOUND(100, 0)
UNSUPPORTED_LICENSE(101, 1)
WRONG_LICENSE_FOR_VERSION(101, 0)

在某些情况下,异常详细信息ID是相同的,应该永远不会发生。很可能有更多的重复,但这个项目是巨大的手工检查...

是否有一种智能方法可以检查重复代码,例如UnitTesting - 从未使用它。

感谢您的帮助!

编辑(当只使用一个枚举时,Bens答案是解决此问题的好方法): 为了更清楚我的具体任务,这就是情况。 编写了许多用于处理ExceptionDetails的类,例如

TopicOneExceptionDetails.java
TopicTwoExceptionDetails.java  (and so on)

这些类中的每一个都定义了这个主题的枚举,如下所示:

public enum TopicOneExceptionDetails implements ApplicationException.ExceptionDetails { .... }

然后声明与TopicOne错误相关的错误,例如

SETTING_TIMEZONE_FAILED(55, ...)
Setting_DATETIME_FAILED(56, ...)

在TopicOne的这个枚举中,每个错误ID都必须是唯一的。但是例如ID 55(此处用于SETTING_TIMEZONE_FAILED)可用于声明与TopicTwo相关的错误而没有问题。

编辑2 (使用反射?) 我找到了一个由pretty informative answer编写的关于java Reflections的{​​{3}}。我认为这可以解决我的问题。我需要休息但我会报告回来。我目前的想法是:

Reflections reflections = new Reflections("project.de")
for(Class<? extends ApplicationException.ExceptionDetails> exceptionDetailsClasses : reflections.getSubTypesOf(ApplicationException.ExceptionDetails.class)){
for ( ... ) .. }

我应该可以查看ID,例如像Ben建议的那样。我稍后会报告。

编辑3 (问题已解决!) 与编辑2中描述的一样,我可以使用reflections轻松解决此问题。

public class ApplicationExceptionDetailsErrorCodeValidationTest {


@Test
  public void validateErrorCodeUniqueness() throws ErrorCodeUniquenessBroken{
    Reflections reflections = new Reflections("de.xyz");
for (Class<? extends ApplicationException.ExceptionDetails> exceptionDetailsClass : reflections.getSubTypesOf(ApplicationException.ExceptionDetails.class)) {
  if (exceptionDetailsClass.getSimpleName().equals("TestExceptionDetails")) {
    continue;
  }

  List<Integer> errorCodes = new ArrayList<Integer>();

  for (ApplicationException.ExceptionDetails exceptionDetails : exceptionDetailsClass.getEnumConstants()) {
    if (errorCodes.contains(exceptionDetails.getErrorCode().getId()))  throw new ErrorCodeUniquenessBroken("ErrorCode uniqueness broken! ErrorCode: " + exceptionDetails.getMessageKey() + " has repeated ErrorCode! Change it!");
    else errorCodes.add(exceptionDetails.getErrorCode().getId());
  }
}

} }

特别感谢Ben和Spotted的努力。两者都回答了一些非常好的例子,说明如何解决一般的主题问题。在我的情况下,它有点复杂。

2 个答案:

答案 0 :(得分:6)

单程检查您的Enum是否有重复ID(未经过测试,但应该可以使用)。
您可以将此代码的一部分用于单元测试(或单独使用):

import java.util.HashSet;
import java.util.Set;

public class NewClass 
{
   public static enum Errors
   {
      ERROR_A(1),
      ERROR_B(2),
      ERROR_C(3),
      ERROR_D(2), //duplicate is here!
      ERROR_E(5);

      int m_id;
      Errors(int id)
      {
          m_id = id;
      }

      public int getId()
      {
          return m_id;
      }
   }

   public static void main(String[] args) 
   {
      Set<Integer> usedIds = new HashSet<>();
      for (Errors e : Errors.values()) //iterate over all Error-Enum-Items
      {
          int id = e.getId(); //fetch id from enum-item
          if (usedIds.contains(id)) //check if id was used before
              System.err.println("ID ALREADY USED: " + e.name() + ":" + id);
          else
              usedIds.add(id); //remember new used id here
      }
   }
}

干杯!

答案 1 :(得分:2)

当然,单位测试是检测(有确定)此类问题的好方法。

import static org.junit.Assert.*;

import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;

import org.junit.Test;

public class ErrorSpec {

    @Test
    public void itShouldNotHaveTwoEnumsWithSameId() {
        Set<Integer> idsWithoutDuplicates = Arrays.stream(Error.values())
                                                  .map(Error::getId)
                                                  .collect(Collectors.toSet());

        assertEquals(Error.values().length, idsWithoutDuplicates.size());
    }
}

如果您希望使用AssertJ,可以使测试更加明确(并指出哪个ID重复!):

import static org.assertj.core.api.Assertions.*;

import java.util.Arrays;
import org.junit.Test;

public class ErrorSpec {

    @Test
    public void itShouldNotHaveTwoEnumsWithSameId() {
        int[] ids = Arrays.stream(Error.values())
                                        .mapToInt(Error::getId)
                                        .toArray();

        assertThat(ids).doesNotHaveDuplicates();
    }
}