Hello! I have a problem with kotlin 1.5.21, 1.5.30, and mocking observers from android lifecycle 2.3.1 with mockk.
It works on kotlin 1.4.32
How to reproduce:
val dialogObserver: Observer<Unit> = mockk()
every { dialogObserver.onChanged(any()) }.returns(Unit)
Log:
Failed matching mocking signature for
SignedCall(retValue=java.lang.Void@91af3b8, isRetValueMock=false, retType=class java.lang.Void, self=Observer(#6), method=onChanged(Any), args=[kotlin.Unit], invocationStr=Observer(#6).onChanged(kotlin.Unit))
left matchers: [any()]
io.mockk.MockKException: Failed matching mocking signature for
SignedCall(retValue=java.lang.Void@91af3b8, isRetValueMock=false, retType=class java.lang.Void, self=Observer(#6), method=onChanged(Any), args=[kotlin.Unit], invocationStr=Observer(#6).onChanged(kotlin.Unit))
left matchers: [any()]
Hello I have updated the gradle to 7.2 and the mockk test are throwing errors
class HelloTest : ShouldSpec({
val mockPrinter = mockk<Printer>()
should("print message") {
coEvery { mockPrinter.print(Name("")) } returns "OK"
val hello = Hello(mockPrinter)
hello.hello("TEST")
}
})
value class Name(val value: String)
interface Printer {
fun print(name: Name): String
}
class Hello(private val printer: Printer) {
fun hello(name: String) {
println(printer.print(Name(name)))
}
}
testImplementation "io.kotest:kotest-runner-junit5:4.6.3"
testImplementation "io.kotest.extensions:kotest-extensions-robolectric:0.4.0"
testImplementation "io.mockk:mockk:1.12.0"
------------------------------------------------------------
Gradle 7.2
------------------------------------------------------------
Build time: 2021-08-17 09:59:03 UTC
Revision: a773786b58bb28710e3dc96c4d1a7063628952ad
Kotlin: 1.5.21
Groovy: 3.0.8
Ant: Apache Ant(TM) version 1.10.9 compiled on September 27 2020
JVM: 11.0.8 (JetBrains s.r.o 11.0.8+10-b944.6916264)
OS: Mac OS X 10.16 x86_64
I'm getting the following errorno answer found for: Printer(#2).print-mtRpO38(TEST)
io.mockk.MockKException: no answer found for: Printer(#2).print-mtRpO38(TEST)
at app//io.mockk.impl.stub.MockKStub.defaultAnswer(MockKStub.kt:93)
at app//io.mockk.impl.stub.MockKStub.answer(MockKStub.kt:42)
at app//io.mockk.impl.recording.states.AnsweringState.call(AnsweringState.kt:16)
at app//io.mockk.impl.recording.CommonCallRecorder.call(CommonCallRecorder.kt:53)
at app//io.mockk.impl.stub.MockKStub.handleInvocation(MockKStub.kt:266)
at app//io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1.invocation(JvmMockFactoryHelper.kt:23)
at app//io.mockk.proxy.jvm.advice.Interceptor.call(Interceptor.kt:21)
at app//io.mockk.proxy.jvm.advice.BaseAdvice.handle(BaseAdvice.kt:42)
at app//io.mockk.proxy.jvm.advice.jvm.JvmMockKProxyInterceptor.interceptNoSuper(JvmMockKProxyInterceptor.java:45)
at app//com.example.junit5example.Printer$Subclass0.print-mtRpO38(Unknown Source)
at app//com.example.junit5example.Hello.hello(MainActivity.kt:216)
at app//com.example.junit5example.HelloTest$1$1.invokeSuspend(RobotTest.kt:85)
at app//com.example.junit5example.HelloTest$1$1.invoke(RobotTest.kt)
at app//com.example.junit5example.HelloTest$1$1.invoke(RobotTest.kt)
at app//io.kotest.core.internal.ExecutionsKt$executeWithBehaviours$2$1.invokeSuspend(executions.kt:13)
I using the laatest version of Android Studio Artic Fox.
has anyone faced a similar issue?
Hi Team, i need need assistance in writing the test for a private function, whose code is as follows, Function Actual Implmentation:
private fun evaluateSealedClassWithCondition(
condition: suspend () -> AppResult<Playlist>,
success: (Playlist) -> Unit, error: (String) -> Unit = {}
) {
launch( handler) {
when (val data = condition()) {
is AppError -> {
withContext(dispatcher.main) {
error(data.message!!)
}
}
is AppSuccess -> {
withContext(dispatcher.main) {
success(data.data)
}
}
}
}
}
fun createEmptyPlayListForCurrentUser() {
evaluateSealedClassWithCondition(condition = {
createPlayListUseCase(selectedUser)
}, success = {
listOfPlayListForCurrentUser.add(it)
})
}
Test File:
@ExtendWith(value = [MockKExtension::class, InstantExecutorExtension::class])
class UserPlayListManagerImplTest {
@JvmField
@RegisterExtension
val coroutinesTestRule = MainCoroutineRule()
@MockK
lateinit var createPlayListUseCase: CreatePlayListUseCase
@MockK
lateinit var addTrackUseCase: AddTrackUseCase
@MockK
lateinit var deleteTrackUseCase: DeleteTrackUseCase
lateinit var userPlayListManager: UserPlayListManagerImpl
@BeforeEach
fun setUp() {
MockKAnnotations.init(this, relaxed = true)
userPlayListManager = spyk(UserPlayListManagerImpl(
coroutinesTestRule.testDispatcherProvider, createPlayListUseCase,
addTrackUseCase, deleteTrackUseCase), recordPrivateCalls = true)
}
@Test
fun `Create an empty playlist for loggedIn User`() = coroutinesTestRule.runBlockingTest {
val condition: suspend () -> AppResult<Playlist> = {
createPlayListUseCase(getTestNormalUser())
}
val success: (Playlist) -> Unit = mockk(relaxed = true)
val error: (String) -> Unit = mockk(relaxed = true)
coEvery {
createPlayListUseCase(any())
} returns AppSuccess(createEmptyPlayList(getTestNormalUser()))
every {
userPlayListManager invoke "evaluateSealedClassWithCondition" withArguments
listOf(condition, success, error)
} returns Unit
userPlayListManager.createEmptyPlayListForCurrentUser()
verify {
userPlayListManager invoke "evaluateSealedClassWithCondition" withArguments
listOf(condition, success, error)
}
}
}
Error:
can't find function evaluateSealedClassWithCondition(() -> app.template.base.useCases.AppResult<reprator.module.modulea.modals.Playlist>, Function1(#5), Function1(#6)) of class reprator.module.modulea.UserPlayListManagerImpl for dynamic call.
If you were trying to verify a private function, make sure to provide type information to exactly match the functions signature.
io.mockk.MockKException: can't find function evaluateSealedClassWithCondition(() -> app.template.base.useCases.AppResult<reprator.module.modulea.modals.Playlist>, Function1(#5), Function1(#6)) of class reprator.module.modulea.UserPlayListManagerImpl for dynamic call.
If you were trying to verify a private function, make sure to provide type information to exactly match the functions signature.
at io.mockk.InternalPlatformDsl.dynamicCall(InternalPlatformDsl.kt:126)
at io.mockk.MockKMatcherScope$DynamicCallLong.withArguments(API.kt:1989)
at reprator.module.modulea.UserPlayListManagerImplTest$Create an empty playlist for loggedIn User$1$2.invoke(UserPlayListManagerImplTest.kt:68)
at reprator.module.modulea.UserPlayListManagerImplTest$Create an empty playlist for loggedIn User$1$2.invoke(UserPlayListManagerImplTest.kt:67)
at io.mockk.impl.eval.RecordedBlockEvaluator$record$block$1.invoke(RecordedBlockEvaluator.kt:25)
at io.mockk.impl.eval.RecordedBlockEvaluator$enhanceWithRethrow$1.invoke(RecordedBlock
For reference, i had posted on stackoverlow, https://stackoverflow.com/questions/69660009/mocking-a-private-function-with-higher-order-function-as-arguement-with-mockk
Hi mates, May i have some of your time for this question posted on stackoveflow, out of curiousity, me in little bit hurry
I'm trying to mockk a subclass of java.util.Map
interface, but failing to mock the .put()
operator fun myMap["key"] = value
, method calls to explicit calls to put()
do get intercepted and mocked, but myMap["key"] =
assignment does not get mocked.
I saw something about instance[""] methods being overloaded by mockk for DynamicCall interception...
is there any way to mock this successfully? or must I only use .put() method, and accept that myMap[" "] assignment will slip through... ? Thanks
this is the JMH code that I used and results
@Benchmark
fun mockk(blackhole: Blackhole) {
runBlocking {
val mock: MockedClass = mockk() {
coEvery { mockedMethod(Param1("param")) } returns Result()
}
blackhole.consume(mock.mockedMethod(Param1("param")))
}
}
@Benchmark
fun mockito(blackhole: Blackhole) {
runBlocking {
val mock: MockedClass = mock() {
onBlocking { mockedMethod(Param1("param")) } doReturn Result()
}
blackhole.consume(mock.mockedMethod(Param1("param")))
}
}
Benchmark Mode Cnt Score Error Units
SISBench.mockito thrpt 10 20.250 ± 0.466 ops/ms
SISBench.mockk thrpt 10 13.251 ± 2.475 ops/ms
It was relatively even slower when verify was used:
SISBench.mockito thrpt 10 12.977 ± 0.194 ops/ms
SISBench.mockk thrpt 10 6.884 ± 1.234 ops/ms
Hello guys!!
I am exploring MockK and trying to write testcase for my Jetpack compose application as below and I am
facing 'io.mockk.MockKException: Can't instantiate proxy via default constructor for class'
Error when Im trying to execute testcase. Below is the code for reference
What am I doing wrong!
Here is my 'Test' class
'''
class SampleTest {
@get:Rule
val composeTestRule = createComposeRule()
private lateinit var sampleViewModel: SampleViewModel
private lateinit var sampleRepo: SampleRepo
private lateinit var context: Context
@ExperimentalMaterialApi
@Before
fun setup() {
composeTestRule.setContent {
context = mockk<Context>(relaxed = true)
sampleRepo = spyk()
sampleViewModel = spyk()
LoadSampleScreenUI()
}
}
}
'''
Here is my 'SampleRepo' class
'''
class SampleRepo @Inject constructor (@ApplicationContext private val context: Context) {
//---------------------
//Repo operations goes here which does some File and Datastore operations based on the context
//---------------------
}
'''
Here is my 'SampleViewModel' class
'''
@HiltViewModel
class SampleViewModel @Inject constructor
(val sampleRepo: SampleRepo) : ViewModel() {
//---------------------------
//Viewmodel based on data from Repo
//---------------------------
}
'''
Here is my 'LoadSampleScreenUI' composable function
'''
@Composable
@ExperimentalMaterialApi
fun LoadSampleScreenUI() {
val viewModel
= hiltViewModel<
SampleViewModel>()
}
'''
Here is the 'stack trace'
'''
io.mockk.MockKException: Can't instantiate proxy via default constructor for class com.abc.xyz.repositories.SampleRepo
at io.mockk.impl.instantiation.JvmMockFactory.newProxy(JvmMockFactory.kt:60)
at io.mockk.impl.instantiation.AbstractMockFactory.newProxy$default(AbstractMockFactory.kt:29)
at io.mockk.impl.instantiation.AbstractMockFactory.spyk(AbstractMockFactory.kt:102)
at com.abc.xyz.SampleTest$setup$1.invoke(SampleTest.kt:130)
at com.abc.xyz.SampleTest$setup$1.invoke(SampleTest.kt:37)
'''
Thanks In Advance.
Hello,
val dto = createTransaction()
val enrichedTransaction =
EnrichedTransaction(
mainId = dto.mainId,
additionalData = mockk(),
)
//this below executes method enrichTransactionTestHarness.send()
enrichTransactionTestHarness.enrich(dto)
verify(exactly=1)
{
enrichTransactionTestHarness.send(
Topic.ENRICH
dto.mainId
enrichedTransaction)
}
I want to verify that enrichTransactionTestHarness.send() was executed BUT WITHOUT checking additionalData. So all passed arguments like topic, dto.mainId and enrichedTransaction (but without additionalData)
Is it possible?
Hi all, I wonder how to mock a method of a Java class with nullable type. By right, I should be able to use any() but for parameters in methods with different signature.
For example, Package class has methods:
Now I only want to mock the first method. String type in Java could be null, so my attempt using String::class is not valid
val package = mockk<Package> {
every { getValue ( any(), String::class)} returns ""
// using every { getValue ( any(), any())} returns "" doesn't work due to ambiguous
}
`
Anybody encountered this issue before?
No other calls allowed in stdObjectAnswer than equals/hashCode/toString
io.mockk.MockKException: No other calls allowed in stdObjectAnswer than equals/hashCode/toString
Actual object 'MockK' has no corresponding expected declaration
Hi everyone, I tried to search for this answer but my Google-fu failed me:
should I call clearAllMocks()
inside the tearDown method in a unit test if I have more than one test using the same mock?
for example, here is not stricktly needed, because I'm explicitely but is it a best practice to do it anyway?:
class MyTest {
private val appDataStoreRepository: DataStoreRepository = mockk()
private lateinit var readEulaIsConfirmedInteractor: ReadEulaIsConfirmedInteractor
@Before
fun setUp() {
readEulaIsConfirmedInteractor = ReadEulaIsConfirmedInteractor(appDataStoreRepository = appDataStoreRepository)
}
@After
fun tearDown() {
clearAllMocks()
}
@Test
fun test1() = runTest {
// Given
coEvery { appDataStoreRepository.readValue(ReadEulaIsConfirmedInteractor.EULA_IS_CONFIRM_PREF_KEY) } returns null
[...]
}
}
@Test
fun test2() = runTest {
// Given
coEvery { appDataStoreRepository.readValue(ReadEulaIsConfirmedInteractor.EULA_IS_CONFIRM_PREF_KEY) } returns null
[...]
}
}
Foo
) which holds a nullable variable of a specific class (let's call it Bar
). I want to set a real object of the class Bar
inside my mocked object Foo
. Later I want to read this set (real) Bar
object from my mocked object Foo
. Is this possible or do you know another way to do it?mockkObject(Foo)
every { Foo.bar } answers { fieldValue }
every { Foo.bar = any() } nullablePropertyType Bar::class answers { fieldValue = value }
Hey all... I'm trying to mockk Instance.now()
without success.
I've tried with this :point_down:
@MockK
private val mockedService: ExampleService
private val now = 1550160535168L
@BeforeEach
fun before() {
mockkStatic(Instant::class)
every { Instant.now() }.returns(Instant.ofEpochMilli(now))
}
@Test
fun test() {
serviceMethod() // internally calls to mockedService.methodA() with Instant.now() as parameter
verify {
mockedService.methodA(Instant.ofEpochMilli(now))
}
}
This is failing due to a Verification failed
message.
Verification failed: call 2 of 3: Instant(child of static Instant#11).truncatedTo(eq(Millis))) was not called
java.lang.AssertionError: Verification failed: call 2 of 3: Instant(child of static Instant#11).truncatedTo(eq(Millis))) was not called
at io.mockk.impl.recording.states.VerifyingState.failIfNotPassed(VerifyingState.kt:66)
at io.mockk.impl.recording.states.VerifyingState.recordingDone(VerifyingState.kt:42)
at io.mockk.impl.recording.CommonCallRecorder.done(CommonCallRecorder.kt:47)
at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:64)
at io.mockk.impl.eval.VerifyBlockEvaluator.verify(VerifyBlockEvaluator.kt:30)
Any idea of what is happening here? Thanks.
Hi , today I upgrade my project to Kotlin 1.7, but some mockk failed the tests.
java.lang.InstantiationError: com.example.demo.UpdateAccountResult
at jdk.internal.reflect.GeneratedSerializationConstructorAccessor18.newInstance(Unknown Source)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:48)
There is a coEvery {}
with a fun and use any()
as params , and return UpdateAccountResult.Sucess()
.
UpdateAccountResult
is sealed class
, there are some data class
es (including Sucess()
) extends it.
every { mockedClass.someMethod(any()) } returns MySealedClass()
[main] WARN io.mockk.proxy.jvm.transformation.JvmInlineInstrumentation - Failed to transform classes [interface nl.dstibbe.MySealedClass]