Repository: unittestbot/utbotjava
Issue: Java fuzzer can't create any values for types with no public constructor (e.g. `LocalDateTime`)

**Description**

When creating instances of arbitrary classes Java fuzzer only considers their accessible constructors. However, some classes (e.g. `LocalDateTime`) only have private constructors while their instances are meant to be created using `static` methods.

**Real world (concrete) example**

Same as in #2428 

**To Reproduce**

Run the following unit test.
```kotlin
@Test
fun `fuzzer can create instances of classes without public constructors but with static factory method in their class`() {
    var seenLocalDateTime = false
    runBlockingWithContext {
        runJavaFuzzing(
            TestIdentityPreservingIdGenerator,
            methodUnderTest = LocalDateTime::getMinute.javaMethod!!.executableId,
            constants = emptyList(),
            names = emptyList(),
        ) { thisInstance, _, _ ->
            val control = runCatching {
                ValueConstructor()
                    .construct(listOfNotNull(thisInstance?.model))
                    .singleOrNull()?.value
            }.getOrNull()?.let { constructedThisInstance ->
                assertInstanceOf(LocalDateTime::class.java, constructedThisInstance)
                seenLocalDateTime = true
                Control.STOP
            } ?: Control.CONTINUE
            BaseFeedback(Trie.emptyNode(), control)
        }
    }
    assertTrue(seenLocalDateTime) { "No value was generated for type LocalDateTime" }
}
```

**Expected behavior**

Test passes.

**Actual behavior**

Test fails.

**Visual proofs (screenshots, logs, images)**

~~~
No value was generated for type LocalDateTime ==> expected: <true> but was: <false>
~~~

Changed files:
utbot-java-fuzzing/src/main/kotlin/org/utbot/fuzzing/providers/Objects.kt, utbot-java-fuzzing/src/test/kotlin/org/utbot/fuzzing/JavaFuzzingTest.kt

diff --git a/utbot-java-fuzzing/src/main/kotlin/org/utbot/fuzzing/providers/Objects.kt b/utbot-java-fuzzing/src/main/kotlin/org/utbot/fuzzing/providers/Objects.kt
index b244761b4..be01e4287 100644
--- a/utbot-java-fuzzing/src/main/kotlin/org/utbot/fuzzing/providers/Objects.kt
+++ b/utbot-java-fuzzing/src/main/kotlin/org/utbot/fuzzing/providers/Objects.kt
@@ -1,6 +1,7 @@
 package org.utbot.fuzzing.providers
 
 import mu.KotlinLogging
+import org.utbot.common.isStatic
 import org.utbot.framework.UtSettings
 import org.utbot.framework.plugin.api.*
 import org.utbot.framework.plugin.api.util.*
@@ -46,33 +47,31 @@ class ObjectValueProvider(
         description: FuzzedDescription,
         type: FuzzedType
     ) = sequence {
-        val classId = type.classId
-        val constructors = classId.allConstructors
-            .filter {
-                isAccessible(it.constructor, description.description.packageName)
-            }
-        constructors.forEach { constructorId ->
-            yield(createValue(classId, constructorId, description))
+        findAccessibleCreators(description, type).forEach { creatorExecutableId ->
+            yield(createValue(type.classId, creatorExecutableId, description))
         }
     }
 
-    private fun createValue(classId: ClassId, constructorId: ConstructorId, description: FuzzedDescription): Seed.Recursive<FuzzedType, FuzzedValue> {
+    private fun createValue(classId: ClassId, creatorExecutableId: ExecutableId, description: FuzzedDescription): Seed.Recursive<FuzzedType, FuzzedValue> {
         return Seed.Recursive(
-            construct = Routine.Create(constructorId.executable.genericParameterTypes.map {
+            construct = Routine.Create(creatorExecutableId.executable.genericParameterTypes.map {
                 toFuzzerType(it, description.typeCache)
             }) { values ->
                 val id = idGenerator.createId()
                 UtAssembleModel(
                     id = id,
                     classId = classId,
-                    modelName = "${constructorId.classId.name}${constructorId.parameters}#" + id.hex(),
+                    modelName = "${creatorExecutableId.classId.name}.${creatorExecutableId.signature}#" + id.hex(),
                     instantiationCall = UtExecutableCallModel(
                         null,
-                        constructorId,
+                        creatorExecutableId,
                         values.map { it.model }),
                     modificationsChainProvider = { mutableListOf() }
                 ).fuzzed {
-                    summary = "%var% = ${classId.simpleName}(${constructorId.parameters.joinToString { it.simpleName }})"
+                    summary = "%var% = ${when (creatorExecutableId) {
+                        is ConstructorId -> classId.simpleName
+                        is MethodId -> creatorExecutableId.simpleNameWithClass
+                    }}(${creatorExecutableId.parameters.joinToString { it.simpleName }})"
                 }
             },
             modify = sequence {
@@ -164,12 +163,8 @@ class AbstractsObjectValueProvider(
                 }
                 val jClass = sc.id.jClass
                 return isAccessible(jClass, description.description.packageName) &&
-                        jClass.declaredConstructors.any { isAccessible(it, description.description.packageName) } &&
-                        jClass.let {
-                            // This won't work in case of implementations with generics like `Impl<T> implements A<T>`.
-                            // Should be reworked with accurate generic matching between all classes.
-                            toFuzzerType(it, description.typeCache).traverseHierarchy(description.typeCache).contains(type)
-                        }
+                        findAccessibleCreators(description, toFuzzerType(jClass, description.typeCache)).any() &&
+                        jClass.let { toFuzzerType(it, description.typeCache).isDefinitelySubtypeOf(description, type) }
             } catch (ignore: Throwable) {
                 return false
             }
@@ -191,6 +186,27 @@ class AbstractsObjectValueProvider(
     }
 }
 
+private fun findAccessibleCreators(
+    description: FuzzedDescription,
+    neededType: FuzzedType
+): Sequence<ExecutableId> =
+    (neededType.classId.allConstructors + (neededType.classId.jClass.methods
+            .filter {
+                it.isStatic && toFuzzerType(it.genericReturnType, description.typeCache)
+                        .isDefinitelySubtypeOf(description, neededType)
+            }
+            .map { it.executableId })
+    ).filter { isAccessible(it.executable, description.description.packageName) }
+
+/**
+ * NOTE: this function takes conservative when generics are involved.
+ *
+ * For example, `false` may be returned when [this] is `List<T>` or `ArrayList<T>` while [other] is `List<String>`.
+ */
+// TODO should be reworked with accurate generic matching
+private fun FuzzedType.isDefinitelySubtypeOf(description: FuzzedDescription, other: FuzzedType): Boolean =
+    classId.isSubtypeOf(other.classId) && traverseHierarchy(description.typeCache).contains(other)
+
 internal class PublicSetterGetter(
     val setter: Method,
     val getter: Method,
diff --git a/utbot-java-fuzzing/src/test/kotlin/org/utbot/fuzzing/JavaFuzzingTest.kt b/utbot-java-fuzzing/src/test/kotlin/org/utbot/fuzzing/JavaFuzzingTest.kt
index 360d70635..b7e60d978 100644
--- a/utbot-java-fuzzing/src/test/kotlin/org/utbot/fuzzing/JavaFuzzingTest.kt
+++ b/utbot-java-fuzzing/src/test/kotlin/org/utbot/fuzzing/JavaFuzzingTest.kt
@@ -24,6 +24,7 @@ import org.utbot.fuzzing.utils.Trie
 import java.lang.reflect.GenericArrayType
 import java.lang.reflect.ParameterizedType
 import java.lang.reflect.Type
+import java.time.LocalDateTime
 import java.util.IdentityHashMap
 import java.util.concurrent.atomic.AtomicInteger
 import kotlin.reflect.jvm.javaMethod
@@ -177,6 +178,31 @@ class JavaFuzzingTest {
         seenStrings.forEach { assertInstanceOf(String::class.java, it) }
     }
 
+    @Test
+    fun `fuzzer can create instances of classes without public constructors but with static factory method in their class`() {
+        var seenLocalDateTime = false
+        runBlockingWithContext {
+            runJavaFuzzing(
+                TestIdentityPreservingIdGenerator,
+                methodUnderTest = LocalDateTime::getMinute.javaMethod!!.executableId,
+                constants = emptyList(),
+                names = emptyList(),
+            ) { thisInstance, _, _ ->
+                val control = runCatching {
+                    ValueConstructor()
+                        .construct(listOfNotNull(thisInstance?.model))
+                        .singleOrNull()?.value
+                }.getOrNull()?.let { constructedThisInstance ->
+                    assertInstanceOf(LocalDateTime::class.java, constructedThisInstance)
+                    seenLocalDateTime = true
+                    Control.STOP
+                } ?: Control.CONTINUE
+                BaseFeedback(Trie.emptyNode(), control)
+            }
+        }
+        assertTrue(seenLocalDateTime) { "No value was generated for type LocalDateTime" }
+    }
+
     @Test
     fun `value providers override every function of fuzzing in simple case`() {
         val provided = MarkerValueProvider<FuzzedType, FuzzedValue, FuzzedDescription>("p")