1

I am using Kotlin 1.7.10 and Mockk 1.12.4 and I have a factory method in the following spring bean class:

@Service
class DataSynchronizationManagerFactoryService(
    private val platformTransactionManager: PlatformTransactionManager
) {
    fun <D : DataDto, E : DbEntity, R : DataSynchronizableRepository<E>> constructDataSynchronisationManager(
        processedEntityType: Class<E>,
        repository: R,
        dataLoaderAndTransformer: DataLoaderAndTransformer<D, E>
    ): DataSynchronisationManager<D, E, R> {
        return DataSynchronisationManager<D, E, R>(
            processedEntityType,
            repository,
            dataLoaderAndTransformer,
            TransactionTemplate(platformTransactionManager)
        )
    }
}

where D, E and R are the following respective interfaces:

public interface DataDto {
    String getSystemId();

}

public interface DbEntity {
    String getSystemId();
}

@NoRepositoryBean
public interface DataSynchronizableRepository<T extends DbEntity> extends
        JpaRepository<T, String>,
        BatchPersistableRepository<T> {

    void deleteBySystemIdIn(Collection<String> systemIds);
}

I am attempting to mock call to the constructDataSynchronisationManager method using Mockk:

every {
    dataSynchronizationManagerFactoryServiceMock
        .constructDataSynchronisationManager<DataDto, DbEntity, DataRepository>(
            any(),
            any(),
            any(),
        )
} returns dataSynchronisationManagerMock

and I am getting the following error:

java.lang.InstantiationError: com.andrew.DataRepository

    at jdk.internal.reflect.GeneratedSerializationConstructorAccessor7.newInstance(Unknown Source)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
    at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:48)
    at io.mockk.proxy.jvm.ObjenesisInstantiator.instanceViaObjenesis(ObjenesisInstantiator.kt:75)
    at io.mockk.proxy.jvm.ObjenesisInstantiator.instance(ObjenesisInstantiator.kt:42)
    at io.mockk.impl.instantiation.JvmInstantiator$instantiate$2.invoke(JvmInstantiator.kt:16)
    at io.mockk.impl.instantiation.AbstractInstantiator.instantiateViaInstanceFactoryRegistry(AbstractInstantiator.kt:17)
    at io.mockk.impl.instantiation.JvmInstantiator.instantiate(JvmInstantiator.kt:15)
    at io.mockk.impl.recording.states.RecordingState$matcher$signatureValue$1$1.invoke(RecordingState.kt:49)
    at io.mockk.impl.instantiation.JvmAnyValueGenerator$anyValue$2.invoke(JvmAnyValueGenerator.kt:35)
    at io.mockk.impl.instantiation.AnyValueGenerator.anyValue(AnyValueGenerator.kt:34)
    at io.mockk.impl.instantiation.JvmAnyValueGenerator.anyValue(JvmAnyValueGenerator.kt:31)
    at io.mockk.impl.recording.states.RecordingState$matcher$signatureValue$1.invoke(RecordingState.kt:48)
    at io.mockk.impl.recording.JvmSignatureValueGenerator.signatureValue(JvmSignatureValueGenerator.kt:20)
    at io.mockk.impl.recording.states.RecordingState.matcher(RecordingState.kt:47)
    at io.mockk.impl.recording.CommonCallRecorder.matcher(CommonCallRecorder.kt:52)

If I create an actual implementation of the DataRepository:

class DataRepositoryImpl: DataRepository<...> {
    // provide empty implementation of all methods
}

and then use the DataRepositoryImpl in the every block to simulate the behavior, the mock goes through, but it is suboptimal because it does not represent the actual code.

Is there a way to mock the call to the generic method so that the InstantiationError does not happen?

Andy
  • 1,127
  • 2
  • 12
  • 25
  • Also see: https://github.com/mockk/mockk/issues/832 – philonous Aug 18 '22 at 13:37
  • @philonous, thank you for the suggestion. I dove a bit deeper into the problem and found it is a bug in the library, which I reported here: https://github.com/mockk/mockk/issues/865. I provided more info there. – Andy Aug 19 '22 at 15:12

0 Answers0