Skip to content

Commit

Permalink
Add RandomClassProvider::randomClassInstance fun with KClass input (#258
Browse files Browse the repository at this point in the history
)
  • Loading branch information
serpro69 authored Feb 18, 2025
1 parent 4279e8a commit 1b0a8c5
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 7 deletions.
2 changes: 2 additions & 0 deletions core/api/core.api
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,9 @@ public final class io/github/serpro69/kfaker/provider/misc/RandomClassProvider {
public final fun copy ()Lio/github/serpro69/kfaker/provider/misc/RandomClassProvider;
public final fun getConfig ()Lio/github/serpro69/kfaker/provider/misc/RandomProviderConfig;
public final fun new ()Lio/github/serpro69/kfaker/provider/misc/RandomClassProvider;
public final fun randomClassInstance (Lkotlin/reflect/KClass;)Ljava/lang/Object;
public final synthetic fun randomClassInstance (Lkotlin/reflect/KClass;Lio/github/serpro69/kfaker/provider/misc/RandomProviderConfig;)Ljava/lang/Object;
public final fun randomClassInstance (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public final fun reset ()V
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.github.serpro69.kfaker.provider.misc

import com.fasterxml.jackson.databind.deser.impl.CreatorCandidate.Param
import io.github.serpro69.kfaker.FakerConfig
import io.github.serpro69.kfaker.RandomService
import io.github.serpro69.kfaker.provider.misc.ConstructorFilterStrategy.MAX_NUM_OF_ARGS
Expand Down Expand Up @@ -107,6 +106,33 @@ class RandomClassProvider {
return T::class.randomClassInstance(RandomProviderConfig().apply(configurator))
}

/**
* Creates an instance of [T] from the [KClass] input.
* If [T] has a parameterless public constructor then it will be used to create an instance of this class,
* otherwise a constructor with minimal number of parameters will be used with randomly-generated values.
*
* @param kClass a [KClass] of [T]
*
* @throws NoSuchElementException if [T] has no public constructor.
*/
fun <T : Any> randomClassInstance(kClass: KClass<T>): T {
return kClass.randomClassInstance(config)
}

/**
* Creates an instance of [T] from the [KClass] input.
* If [T] has a parameterless public constructor then it will be used to create an instance of this class,
* otherwise a constructor with minimal number of parameters will be used with randomly-generated values.
*
* @param kClass a [KClass] of [T]
* @param configurator configure instance creation.
*
* @throws NoSuchElementException if [T] has no public constructor.
*/
fun <T : Any> randomClassInstance(kClass: KClass<T>, configurator: RandomProviderConfig.() -> Unit): T {
return kClass.randomClassInstance(RandomProviderConfig().apply(configurator))
}

@Suppress("UNCHECKED_CAST")
@JvmSynthetic
@PublishedApi
Expand Down Expand Up @@ -250,7 +276,8 @@ class RandomClassProvider {
Map::class -> {
val keyElementType = kType.arguments[0].type?.classifier as KClass<*>
val valElementType = kType.arguments[1].type?.classifier as KClass<*>
val keys = List(config.collectionsSize) { instance(config.mapEntriesTypeGenerators.first, keyElementType) }
val keys =
List(config.collectionsSize) { instance(config.mapEntriesTypeGenerators.first, keyElementType) }
keys.associateWith { instance(config.mapEntriesTypeGenerators.second, valElementType) }
}
else -> null
Expand Down Expand Up @@ -389,9 +416,15 @@ private fun RandomProviderConfig.copy(
this@apply.namedParameterGenerators.putAll(namedParameterGenerators ?: this@copy.namedParameterGenerators)
this@apply.predefinedGenerators.putAll(predefinedGenerators ?: this@copy.predefinedGenerators)
this@apply.nullableGenerators.putAll(nullableGenerators ?: this@copy.nullableGenerators)
this@apply.collectionElementTypeGenerators.putAll(collectionElementTypeGenerators ?: this@copy.collectionElementTypeGenerators)
this@apply.mapEntriesTypeGenerators.first.putAll(mapEntriesTypeGenerators?.first ?: this@copy.mapEntriesTypeGenerators.first)
this@apply.mapEntriesTypeGenerators.second.putAll(mapEntriesTypeGenerators?.second ?: this@copy.mapEntriesTypeGenerators.second)
this@apply.collectionElementTypeGenerators.putAll(
collectionElementTypeGenerators ?: this@copy.collectionElementTypeGenerators
)
this@apply.mapEntriesTypeGenerators.first.putAll(
mapEntriesTypeGenerators?.first ?: this@copy.mapEntriesTypeGenerators.first
)
this@apply.mapEntriesTypeGenerators.second.putAll(
mapEntriesTypeGenerators?.second ?: this@copy.mapEntriesTypeGenerators.second
)
}

enum class FallbackStrategy {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ import io.kotest.core.spec.style.DescribeSpec
import io.kotest.matchers.collections.containOnly
import io.kotest.matchers.collections.shouldContain
import io.kotest.matchers.collections.shouldContainAnyOf
import io.kotest.matchers.collections.shouldContainOnly
import io.kotest.matchers.collections.shouldHaveSize
import io.kotest.matchers.collections.shouldNotContain
import io.kotest.matchers.collections.shouldNotContainOnly
import io.kotest.matchers.ints.shouldBeInRange
import io.kotest.matchers.maps.shouldHaveSize
import io.kotest.matchers.shouldBe
Expand Down Expand Up @@ -43,6 +41,14 @@ class RandomClassProviderTest : DescribeSpec({
testClass shouldBe instanceOf(TestClass::class)
}
}

context("creating a random instance from kClass") {
val testClass: TestClass = randomProvider.randomClassInstance(TestClass::class)

it("it should be instance of TestClass") {
testClass shouldBe instanceOf(TestClass::class)
}
}
}

describe("a TestClass with non-empty constructor") {
Expand Down Expand Up @@ -514,6 +520,7 @@ class RandomClassProviderTest : DescribeSpec({

it("should generate null elements in collections") {
data class Nullable(val ints: List<Int?>, val longs: Set<Long?>, val map: Map<Char?, String?>)

val nullable = randomProvider.randomClassInstance<Nullable> {
collectionsSize = 10
collectionElementTypeGenerator<Int?> { if (random.nextBoolean()) null else 42 }
Expand Down

0 comments on commit 1b0a8c5

Please sign in to comment.