1

I have the empty interface interface HavingUniqueValues(val v: Int) {} and some enums like enum class EnumName(override val v: Int) : HavingUniqueValues.

I want the elements in each enum have unique v-values but I can mistype the values. So I need a test.

  1. Is it possible to create a test where the interface implementations are saved as a List manually and the test checks if all the implementations in the List meet the requirement?
  2. If yes: is it possible to create a function that returns the List of all implementations in the specified package to use it in the test?
SerVB
  • 129
  • 17

3 Answers3

3

Take a look at the Reflections library which might aid you with this.

You should be able to get all subtypes of HavingUniqueValues:

val subjects: Set<Class<out HavingUniqueValues>> =
        Reflections("your.package").getSubTypesOf(HavingUniqueValues::class.java)

Now, this will result in a Set of all enum classes that implement HavingUniqueValues. You can iterate all of their values to know if they are unique or not:

subjects.forEach { enumClass ->
    assertEquals(
            enumClass.enumConstants.size,
            enumClass.enumConstants.map(HavingUniqueValues::v).toSet().size
    )
}

I used toSet() here to drop all non-inuque values.

This will pass the test:

enum class EnumName(override val v: Int) : HavingUniqueValues { ONE(1), TWO(2), THREE(3) }

This will not pass the test:

enum class EnumName(override val v: Int) : HavingUniqueValues { ONE(1), TWO(2), THREE(2) }
Egor Neliuba
  • 14,784
  • 7
  • 59
  • 77
2

I tried accepted solution and it didn't work with enums. It seems Reflectons library doesn't support searching for implementations that are custom Enums, Exceptions etc. At least with default configuration provided in above answer. There are lot of links and documentation that answer why it won't work:

Why doesn't reflections.getSubTypesOf(Object.class) find enums?

https://github.com/ronmamo/reflections/issues/126

I was able to find and test similar solution with Classgraph

Here is example code that worked for me with enums:

try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("package.with.your.enums").scan()) {
    ClassInfoList implementationsRefs = scanResult.getClassesImplementing("package.with.your.enums.yourInterfaceForEnums");
    List<Class<?>> implementations = implementationsRefs.loadClasses();
    //here goes your code that operates on "implementations"
}
Daimonion
  • 61
  • 3
1

Since you tagged your question with kotlintest, I've turned @egor's excellent answer into a KotlinTest copy n paste snippet for you.

class MyTest : StringSpec({

  "unique values" {

    val subjects: Set<Class<out HavingUniqueValues>> =
        Reflections("your.package").getSubTypesOf(HavingUniqueValues::class.java)

    subjects.forEach { enumClass ->
      enumClass.enumConstants.size shouldBe
          enumClass.enumConstants.map(HavingUniqueValues::v).toSet().size
    }
  }

})
sksamuel
  • 16,154
  • 8
  • 60
  • 108