Протестируйте все перечисления, реализующие интерфейс маркера
У меня пустой интерфейс interface HavingUniqueValues(val v: Int) {}
и некоторые перечисления, как enum class EnumName(override val v: Int) : HavingUniqueValues
,
Я хочу, чтобы элементы в каждом перечислении были уникальными v
-значения, но я могу неправильно набирать значения. Поэтому мне нужен тест.
- Можно ли создать тест, в котором реализации интерфейса сохраняются как
List
вручную и тест проверяет, все ли реализации вList
соответствовать требованию? - Если да: возможно ли создать функцию, которая возвращает
List
из всех реализаций в указанном пакете, чтобы использовать его в тесте?
2 ответа
Взгляните на библиотеку Reflections, которая может вам в этом помочь.
Вы должны быть в состоянии получить все подтипы HavingUniqueValues
:
val subjects: Set<Class<out HavingUniqueValues>> =
Reflections("your.package").getSubTypesOf(HavingUniqueValues::class.java)
Теперь это приведет к набору всех перечисляемых классов, которые реализуют HavingUniqueValues
, Вы можете перебрать все их значения, чтобы узнать, являются ли они уникальными или нет:
subjects.forEach { enumClass ->
assertEquals(
enumClass.enumConstants.size,
enumClass.enumConstants.map(HavingUniqueValues::v).toSet().size
)
}
я использовал toSet()
здесь, чтобы отбросить все неинекционные значения.
Это пройдет тест:
enum class EnumName(override val v: Int) : HavingUniqueValues { ONE(1), TWO(2), THREE(3) }
Это не пройдет тест:
enum class EnumName(override val v: Int) : HavingUniqueValues { ONE(1), TWO(2), THREE(2) }
Я попробовал принятое решение, и оно не сработало с перечислениями. Кажется, что библиотека Reflectons не поддерживает поиск реализаций, которые являются настраиваемыми перечислениями, исключениями и т. Д. По крайней мере, с конфигурацией по умолчанию, указанной в приведенном выше ответе. Есть много ссылок и документации, которые объясняют, почему это не сработает:
Почему Reflection.getSubTypesOf(Object.class) не находит перечисления?
https://github.com/ronmamo/reflections/issues/126
Мне удалось найти и протестировать подобное решение с помощью Classgraph
Вот пример кода, который работал у меня с перечислениями:
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"
}
Поскольку вы отметили свой вопрос kotlintest
Я превратил отличный ответ @egor в фрагмент кода KotlinTest для вас.
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
}
}
})