All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jvmMain.io.kotest.matchers.reflection.classMatchers.kt Maven / Gradle / Ivy

package io.kotest.matchers.reflection

import io.kotest.matchers.Matcher
import io.kotest.matchers.MatcherResult
import io.kotest.matchers.should
import io.kotest.matchers.shouldNot
import kotlin.reflect.KClass
import kotlin.reflect.KFunction
import kotlin.reflect.KProperty
import kotlin.reflect.KVisibility
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.isSubclassOf
import kotlin.reflect.full.isSuperclassOf
import kotlin.reflect.full.primaryConstructor

fun KClass<*>.shouldHaveAnnotations() = this should haveClassAnnotations()
fun KClass<*>.shouldNotHaveAnnotations() = this shouldNot haveClassAnnotations()
infix fun KClass<*>.shouldHaveAnnotations(count: Int) = this should haveClassAnnotations(count)
infix fun KClass<*>.shouldNotHaveAnnotations(count: Int) = this shouldNot haveClassAnnotations(count)
@Deprecated("This method has a typo in its name, use the one without the typo", ReplaceWith("haveClassAnnotations(count)"))
fun haveClassAnnontations(count: Int = -1) = haveClassAnnotations(count)
fun haveClassAnnotations(count: Int = -1) = object : Matcher> {
  override fun test(value: KClass<*>) = if (count < 0) {
     MatcherResult(
        value.annotations.isNotEmpty(),
        { "Class $value should have annotations" },
        {
           "Class $value should not have annotations"
        })
  } else {
     MatcherResult(
        value.annotations.size == count,
        { "Class $value should have $count annotations" },
        {
           "Class $value should not have $count annotations"
        })
  }
}

inline fun  KClass<*>.shouldBeAnnotatedWith(block: (T) -> Unit = {}) {
  this should beClassAnnotatedWith()
  findAnnotation()?.let(block)
}

inline fun  KClass<*>.shouldNotBeAnnotatedWith() = this shouldNot beClassAnnotatedWith()
inline fun  beClassAnnotatedWith() = object : Matcher> {
   override fun test(value: KClass<*>) = MatcherResult(
      value.findAnnotation() != null,
      { "Class $value should have annotation ${T::class}" },
      {
         "Class $value should not have annotation ${T::class}"
      })
}

fun KClass<*>.shouldHaveFunction(name: String, block: (KFunction<*>) -> Unit) {
  this should haveFunction(name)
  findFunction(name)?.let(block)
}

infix fun KClass<*>.shouldHaveFunction(name: String) = this should haveFunction(name)
infix fun KClass<*>.shouldNotHaveFunction(name: String) = this shouldNot haveFunction(name)
fun haveFunction(name: String) = object : Matcher> {
   override fun test(value: KClass<*>) = MatcherResult(
      value.findFunction(name) != null,
      { "Class $value should have function $name" },
      {
         "Class $value should not have function $name"
      })
}

fun KClass<*>.shouldHaveMemberProperty(name: String, block: (KProperty<*>) -> Unit) {
  this should haveMemberProperty(name)
  findMemberProperty(name)?.let(block)
}
infix fun KClass<*>.shouldHaveMemberProperty(name: String) = this should haveMemberProperty(name)
infix fun KClass<*>.shouldNotHaveMemberProperty(name: String) = this shouldNot haveMemberProperty(name)
fun haveMemberProperty(name: String) = object : Matcher> {
   override fun test(value: KClass<*>) = MatcherResult(
      value.findMemberProperty(name) != null,
      { "Class $value should have a member property $name" },
      {
         "Class $value should not have a member property $name"
      })
}

inline fun  KClass<*>.shouldBeSubtypeOf() = this should beSubtypeOf()
inline fun  KClass<*>.shouldNotBeSubtypeOf() = this shouldNot beSubtypeOf()
inline fun  beSubtypeOf() = object : Matcher> {
   override fun test(value: KClass<*>) = MatcherResult(
      value.isSubclassOf(T::class),
      { "Class $value should be subtype of ${T::class}" },
      {
         "Class $value should not be subtype of ${T::class}"
      })
}

inline fun  KClass<*>.shouldBeSupertypeOf() = this should beSuperTypeOf()
inline fun  KClass<*>.shouldNotBeSupertypeOf() = this shouldNot beSuperTypeOf()
inline fun  beSuperTypeOf() = object : Matcher> {
   override fun test(value: KClass<*>) = MatcherResult(
      value.isSuperclassOf(T::class),
      { "Class $value should be subtype of ${T::class}" },
      {
         "Class $value should not be subtype of ${T::class}"
      })
}

fun KClass<*>.shouldBeData() = this should beData()
fun KClass<*>.shouldNotBeData() = this shouldNot beData()
fun beData() = object : Matcher> {
   override fun test(value: KClass<*>) = MatcherResult(
      value.isData,
      { "Class $value should be a data class" },
      {
         "Class $value should not be a data class"
      })
}

fun KClass<*>.shouldBeSealed() = this should beSealed()
fun KClass<*>.shouldNotBeSealed() = this shouldNot beSealed()
fun beSealed() = object : Matcher> {
   override fun test(value: KClass<*>) = MatcherResult(
      value.isSealed,
      { "Class $value should be a sealed class" },
      {
         "Class $value should not be a sealed class"
      })
}

fun KClass<*>.shouldBeCompanion() = this should beCompanion()
fun KClass<*>.shouldNotBeCompanion() = this shouldNot beCompanion()
fun beCompanion() = object : Matcher> {
   override fun test(value: KClass<*>) = MatcherResult(
      value.isCompanion,
      { "Class $value should be a companion object" },
      {
         "Class $value should not be a companion object"
      })
}

fun KClass<*>.shouldHavePrimaryConstructor() = this should havePrimaryConstructor()
fun KClass<*>.shouldNotHavePrimaryConstructor() = this shouldNot havePrimaryConstructor()
fun havePrimaryConstructor() = object : Matcher> {
   override fun test(value: KClass<*>) = MatcherResult(
      value.primaryConstructor != null,
      { "Class $value should have a primary constructor" },
      {
         "Class $value should not have a primary constructor"
      })
}

infix fun KClass<*>.shouldHaveVisibility(expected: KVisibility) = this should haveClassVisibility(expected)
infix fun KClass<*>.shouldNotHaveVisibility(expected: KVisibility) = this shouldNot haveClassVisibility(expected)
fun haveClassVisibility(expected: KVisibility) = object : Matcher> {
   override fun test(value: KClass<*>) = MatcherResult(
      value.visibility == expected,
      { "Class $value should have visibility ${expected.humanName()}" },
      {
         "Class $value should not have visibility ${expected.humanName()}"
      })
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy