Skip to content
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

Mockk does not have expectations #610

Closed
androidfred opened this issue Apr 28, 2021 · 3 comments
Closed

Mockk does not have expectations #610

androidfred opened this issue Apr 28, 2021 · 3 comments

Comments

@androidfred
Copy link

androidfred commented Apr 28, 2021

SUMMARY
Mockk does not have expectations, so the user ends up having to write both every and verify statements in many tests.

LONGER VERSION
Imagine this class

class DelegatingWriter(
    private val legacyWriter: LegacyWriter,
    private val jdbiWriter: JdbiWriter
) {

    fun insert(toBeInserted: User) {
        legacyWriter.insert(toBeInserted)
        jdbiWriter.insert(toBeInserted)
    }
}

and this test (this is just an example to illustrate a point, let's not worry about how good or bad of a test this is)

class DelegatingWriterTest {

    @MockK
    lateinit var legacyWriter: LegacyWriter
    @MockK
    lateinit var jdbiWriter: JdbiWriter

    lateinit var delegatingWriter: DelegatingWriter

    @Test
    fun insertHappyPath() {
        every { mockkLegacyWriter.insert(any()) } just runs
        every { mockkJdbiWriter.insert(any()) } just runs
        delegatingWriter.insert(someUser)
    }
}

everything passes, great. Now imagine someone comes in and comments out one of the inserts

class DelegatingWriter(
    private val legacyWriter: LegacyWriter,
    private val jdbiWriter: JdbiWriter
) {

    fun insert(toBeInserted: User) {
        legacyWriter.insert(toBeInserted)
        //jdbiWriter.insert(toBeInserted) commented out
    }
}

the test

    @Test
    fun insertHappyPath() {
        every { mockkLegacyWriter.insert(any()) } just runs
        every { mockkJdbiWriter.insert(any()) } just runs
        delegatingWriter.insert(someUser)
    }

will still (undesirably) pass - verify statements need to be added in order to make it fail.

    @Test
    fun insertHappyPath() {
        every { mockkLegacyWriter.insert(any()) } just runs
        every { mockkJdbiWriter.insert(any()) } just runs
        delegatingWriter.insert(someUser)
        verify { legacyPartnerRoleWriter.insert(any()) }
        verify { jdbiWriteRepository.writeResourceGrant(any()) } //will fail as desired
    }

= Mockk doesn't consider every statements to be expectations, and doesn't fail if specced every statements never get called. Having to always add both every statements and verify statements to so many tests is kind of redundant. Other frameworks do have expectations - it would be nice if expectations were added to Mock as well.

eg

    @Test
    fun insertHappyPath() {
        expect { mockkLegacyWriter.insert(any()) } just runs
        expect { mockkJdbiWriter.insert(any()) } just runs
        delegatingWriter.insert(someUser)
    }

which fails when

class DelegatingWriter(
    private val legacyWriter: LegacyWriter,
    private val jdbiWriter: JdbiWriter
) {

    fun insert(toBeInserted: User) {
        legacyWriter.insert(toBeInserted)
        //jdbiWriter.insert(toBeInserted) commented out
    }
}
@Raibaz
Copy link
Collaborator

Raibaz commented Apr 28, 2021

Hi, thanks a lot for submitting this and for the detailed explanation.

Could it be that this is, actually, a duplicate of #334? If I understand correctly, the behavior you would like to see is the same described in that issue.

@androidfred
Copy link
Author

@Raibaz Yeah, I'd say #334 is a similar ask, but I would prefer adding a new concept/keyword "expect" (or, in case "expect" is a reserved keyword or something, "expectation" or whatever), rather than mess with the existing "every" keyword and it's behavior through config as suggested in #334.

This is perhaps mostly just personal taste - I personally have an intuitive dislike of that kind of magic config that changes behavior of things in non-obvious ways.

@Raibaz
Copy link
Collaborator

Raibaz commented May 4, 2021

Yep I agree it's mostly about personal taste.

In my opinion having a different keyword for stubbed behaviors that need to be executed for the test to pass may lead to users mixing every and expect together in the same test, which seems pretty confusing to me.

I think it would be clearer to declare a test class as using strict mode, or maybe even being able to configure mockk to always use strict mode by default with a global setting.

Closing this for now, then.

@Raibaz Raibaz closed this as completed May 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants