0

In a very huge project, there are alot of ExceptionClasses where exception details are implemented as enum.

NAME_OF_EXCEPTION_DETAIL(ID, PRIORITY)

e.g:

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

In some cases the exception details ID is the same, wich should never have happend. It is pretty damn possible that there are more duplicates but this project is to huge to check this by hand ...

Is there a smart way to check the code for duplicates, e.g. UnitTesting - never used it befor.

Thank's for your help!

Edit (Bens answer is a good way to solve this problem when using just one enum): To be more clear in my specific task this are the circumstances. There are alot of Classes that are written to handle ExceptionDetails e.g.

TopicOneExceptionDetails.java
TopicTwoExceptionDetails.java  (and so on)

Each of these classes defindes a enum for this topic like so:

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

followed by the declaration of errors related to TopicOne errors e.g.

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

in this enum for TopicOne every error ID has to be unique. But for example ID 55 (here used for SETTING_TIMEZONE_FAILED) can be used in the declaration of errors related to TopicTwo without a problem.

Edit 2 (Use reflections ?) I found a pretty informative answer about java Reflections written by Matt Sheppard. I think this could solve my problem. I need to take a break but i will report back. My current thinkings are:

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

I should be able to check for the IDs e.g. like Ben advised. I'll report back later.

EDIT 3 (Question Solved!) Like in edit 2 described i was able to easily solve this issue using 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());
  }
}

} }

Special thanks to Ben and Spotted for their effort. The both answered with some pretty good examples in how to resolve the topics question in general. In my case it just got a bit more complicated.

Community
  • 1
  • 1
Chrizzldi
  • 521
  • 1
  • 8
  • 22
  • 1
    In the enum constructor a check could be implemented against a static table. – Henry Oct 13 '16 at 10:48
  • thats interesting, thank you. how should this look like? – Chrizzldi Oct 13 '16 at 10:52
  • there are alot of exptionclasses with their own exception ids in their specific exeptions. so comparing to a static tabel would result in more than one static table? if i think about this i am pretty sure i have to implement this check in every expectiondetails calls - right? – Chrizzldi Oct 13 '16 at 10:59
  • You mean there are many different enums? – Henry Oct 13 '16 at 11:02
  • see my answer, maybe it can help.... – Ben Oct 13 '16 at 11:05
  • @Henry, yes exactly and in this different enums the ids start by 1 and increase, that is allowed, it is not allowed to have same ids for two different exeptiondetails in the same enum entry. – Chrizzldi Oct 13 '16 at 11:08
  • You know that using an ID, which additionally must be globally unique, contradicts the idea of enums, do you? – Florian Albrecht Oct 13 '16 at 11:19
  • @Florian Albrecht, i did not create this project and i am currently trying to understand what it is about. As far as i see, the ID is not globally unique, just in the specific enum. But thank you anyway, i did not know that globally unique contradicts the idea of enums :). Now i know it. – Chrizzldi Oct 13 '16 at 11:40

2 Answers2

6

One way to check your Enum for duplicate IDs (It's not tested, but should work).
You can use parts of this code for your unit-test (or use it standalone):

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

Cheers!

Ben
  • 3,378
  • 30
  • 46
  • Hi Ben, thanks for you answer. I see the point and like the idea. Infact there are so many exeptiondetail classes, that it would be an huge amount of work to find them all. another problem is, that it is allowed to have the same id if the exeptiondetails class differs from another class with same id. what i figured out so far is, that all exceptiondetails classes inherit from an abstract class applicationexception where i maybe can check it? i dont know. – Chrizzldi Oct 13 '16 at 11:07
  • Would you like to add some more example code to your question? I cannot really imagine/visualize how it is implemented. An enum cannot inherit from other enums. – Ben Oct 13 '16 at 11:15
2

Sure unit testing is a great way to detect (with certitude) such problem.

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

If you wish to use AssertJ you can make the test even more explicit (and also point out which ID is duplicated !):

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();
    }
}
Spotted
  • 4,021
  • 17
  • 33
  • Thank you Spotted, its good to know that unit testing could bring me further here. But i am not sure if i understand your example. If i thest it like this where is my enum adressed to checkthe ids? – Chrizzldi Oct 13 '16 at 11:36
  • @Chrizzldi The first lines retrieve all the IDs from `Error` and store them in a `Set`, thus removing eventual duplicates. In the `assertEquals` if both the size of the `Set` and the number of values in the `enum` are equals, it means that there are no duplicate IDs. – Spotted Oct 13 '16 at 11:42
  • @Chrizzldi: It's basically the same as mine, only with use of **lambdas** and **streams** (needs at least **Java 8**) and put into a unit test `assertEquals` here only shows that there is a duplicate, not which ID exactly. So that may not really help. – Ben Oct 13 '16 at 11:42
  • @Spotted, thank you so much for your effort. I have an idea (see my Edit2) to figure this out. Need to take a break now but ill report back. – Chrizzldi Oct 13 '16 at 12:01
  • @Ben I wanted to show to the OP how convenient it is to verify such things with unit tests. – Spotted Oct 13 '16 at 12:06