8000 Partial mocking and unnecessary stubbings feature conflict · Issue #1345 · mockk/mockk · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Partial mocking and unnecessary stubbings feature conflict #1345

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
8000
ghilainm opened this issue Feb 5, 2025 · 1 comment
Open

Partial mocking and unnecessary stubbings feature conflict #1345

ghilainm opened this issue Feb 5, 2025 · 1 comment

Comments

@ghilainm
Copy link
ghilainm commented Feb 5, 2025

When activating CheckUnnecessaryStub and using partial mocking feature, an unnecessary stubb is wrongly detected when a mock which is a property of the object partially mocked. Below is a minimal example to reproduce the issue.

Non working example (multiplier as a property):

import io.mockk.every
import io.mockk.junit5.MockKExtension
import io.mockk.mockk
import org.junit.jupiter.api.extension.ExtendWith
import kotlin.test.Test
import kotlin.test.assertEquals

data class Multiplier(
    val value: Int,
)

// Class to be tested
class Calculator(
    val multiplier: Multiplier,
) {
    // Call original
    fun multiply(a: Int): Int = a * multiplier.value
}

@ExtendWith(MockKExtension::class)
@MockKExtension.CheckUnnecessaryStub
class CalculatorTest {
    @Test
    fun `test partial mocking and unnecessary stubbing`() {
        val calculator = mockk<Calculator>()
        // Partial mock
        every { calculator.multiply(2) } answers { callOriginal() }

        val multiplier = mockk<Multiplier>()
        every { calculator.multiplier } returns multiplier
        every { multiplier.value } returns 10

        assertEquals(20, calculator.multiply(2))
    }
}

Code above raises the following error:

Unnecessary stubbings detected.
Following stubbings are not used, either because there are unnecessary or because tested code doesn't call them :

  1. Calculator(#​1).getMultiplier())
    java.lang.AssertionError: Unnecessary stubbings detected.
    Following stubbings are not used, either because there are unnecessary or because tested code doesn't call them :

  2. Calculator(#​1).getMultiplier())
    at io.mockk.impl.recording.CommonVerificationAcknowledger.checkUnnecessaryStubHelper(CommonVerificationAcknowledger.kt:79)
    at io.mockk.impl.recording.CommonVerificationAcknowledger.checkUnnecessaryStub(CommonVerificationAcknowledger.kt:30)
    at io.mockk.MockKDsl.internalCheckUnnecessaryStub(API.kt:287)
    at io.mockk.MockKKt.checkUnnecessaryStub(MockK.kt:400)
    at io.mockk.junit5.MockKExtension.afterAll(MockKExtension.kt:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1597)

Working Example (multiplier as function)

import io.mockk.every
import io.mockk.junit5.MockKExtension
import io.mockk.mockk
import org.junit.jupiter.api.extension.ExtendWith
import kotlin.test.Test
import kotlin.test.assertEquals

data class Multiplier(
    val value: Int,
)

// Class to be tested
class Calculator {
    fun multiplier() = Multiplier(5)

    // Call original
    fun multiply(a: Int): Int = a * multiplier().value
}

@ExtendWith(MockKExtension::class)
@MockKExtension.CheckUnnecessaryStub
class CalculatorTest {
    @Test
    fun `test partial mocking and unnecessary stubbing`() {
        val calculator = mockk<Calculator>()
        // Partial mock
        every { calculator.multiply(2) } answers { callOriginal() }

        val multiplier = mockk<Multiplier>()
        every { calculator.multiplier() } returns multiplier
        every { multiplier.value } returns 10

        assertEquals(20, calculator.multiply(2))
    }
}
@VitalyVPinchuk
Copy link
Contributor
VitalyVPinchuk commented Apr 23, 2025

Hi
I think it comes down to this:

class CTest {
    class C {
        open val a = 1
        val b = 1 // the issue, b is final
        fun c() = 1
        fun op() = a + b + c()
    }

    @Test
    fun `track final value`() {
        val mock = mockk<C>()
        every { mock.a } returns 2
        every { mock.b } returns 2
        every { mock.c() } answers { 2 }
        every { mock.op() } answers { callOriginal() }

        assertEquals(6, mock.op()) // ok
        verify { mock.a }
        verify { mock.b } // fails
        verify { mock.c() }
    }
}

@Raibaz Is there a way to track final val?

Sign up for free to join this conversation on GitHub. Already have an account? Sign 40C3 in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants
0