-
Notifications
You must be signed in to change notification settings - Fork 624
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
Add documentation for usage with Mockk
and other mock libraries
#583
Comments
Side point to possibly consider: Resetting mocks meaning re-initializing them which isn't always so efficient. One way or the other it might be worth it to consider a standard way to "hook" into the test executions to reset existing (in Mockk there's the Or maybe supporting some kind of |
So taking what @dave08 says into account, perhaps we could have an extension |
The problem is when should mocks be cleared. After Test? After Spec? |
Yes that's a good point. |
I think that if we want to keep the default expected behavior for most of mockk users, it would be to clear after test. I think it's important to document both ways too, as a default behavior won't be good enough for some users |
By setting the isolation mode, your mocks will be created correctly and will fit in with the natural state of the rest of your spec variables. There's nothing more required than that to make it work properly. But we can look at an extension which could reset mocks (after every leaf test or after every test - two extensions just extending from a parent), in case you don't want to use a different isolation mode. |
Apart from resetting mocks, for actual creation there's this from Mockk documentation (for JUnit), there's relaxed settings to consider and spies, I wonder if this ...
@MockK
lateinit var car1: Car
@RelaxedMockK
lateinit var car2: Car
@MockK(relaxUnitFun = true)
lateinit var car3: Car
@SpyK
var car4 = Car()
@InjectMockKs
var trafficSystem = TrafficSystem()
@Before
fun setUp() = MockKAnnotations.init(this, relaxUnitFun = true) // turn relaxUnitFun on for all mocks
... Now that I think of it, this is simpler than resetting.. since there's lots of types to handle (constructorMocks, staticMocks, and regular mocks) with differing clear methods. Clearing might be better served with real before/afterXXX DSL methods, but it still needs to be decided if you want to include those... |
Initing mocks via annotations probably work just fine with
I think one can use However, I don't believe that the usual way of using The usual way I use mockks is with val mocked: Database = mockk(relaxed = true)
init {
"Foo" {
every { mocked.getData() } returns null
}
} |
I think that the issue we want to solve is with these variables that are mocked and when they should be reset. I think we should be somewhat agnostic to Mockk's implementation |
I also don't use the annotation form, but by initializing the mocks the regular way, it's either resetting the mocks or using one class per test... I like to stay away from DI's in regular unit tests (not integration tests where there's no choice...), so the annotations are maybe an option. Another option could be Delegate properties to do the same (somewhat like Spek's Btw you mean: |
MockK supports a lot of ways to clear/unmockk and this is very confusing. Extension as well exists, but it does not clear any mocks, just initialize to new instances:
|
|
One possible thing to do is create an extension function for some scope that |
@Kerooker lets create documentation now, showing an example with an IsolationMode, because 3.2 is about to be released. We can do something cleverer for 3.3 if required. |
Documentation would be appreciated. It would be nice to see a constructor injection example without relaxed = true as that is a "sensible default" provided by mockk.
|
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Reviving this issue from the dead, as some documentation around kotest + Mockk would still be nice. I've just started trying out a load of test & mock frameworks for Android and kotest & mockk seem nice given their kotlin based nature. I struggled initially setting them up together. I'll share with you my failed naive attempts so you know what a newbie might do after reading the getting started readme... These two fail with
On reading up on kotest styles, it was mentioned that the two style are functionally equivalent. However I tried the other style (using the init{} block) and suddenly everything worked as expected:
Not quite though, as the This is either a bug or just somethin that needs documenting for newbies like me :) |
It could be because MockK only scans top level fields.
@kerooker is that the case ?
…On Sun, 12 Apr 2020 at 10:00, Oliver Culley de Lange < ***@***.***> wrote:
Reviving this issue from the dead, as some documentation around kotest +
Mockk would still be nice. I've just started trying out a load of test &
mock frameworks for Android and kotest & mockk seem nice given their kotlin
based nature. I struggled initially setting them up together. I'll share
with you my failed naive attempts so you know what a newbie might do after
reading the getting started readme...
These two fail with kotlin.UninitializedPropertyAccessException: lateinit
property thing has not been initialized
class FirstAttemptSpec : FreeSpec({
@mockk
lateinit var thing: Thing
beforeTest {
MockKAnnotations.init(this)
}
"Test something"{
every { thing.name } returns "Blah"
thing.name shouldBe "Blah"
}
})
@ExtendWith(MockKExtension::class)
class SecondAttemptSpec : FreeSpec({
@mockk
lateinit var thing: Thing
"Test something"{
every { thing.name } returns "Blah"
thing.name shouldBe "Blah"
}
})
On reading up on kotest styles
<https://github.com/kotest/kotest/blob/master/doc/reference.md#testing-styles>,
it was mentioned that the two style are functionally equivalent. However I
tried the other style (using the init{} block) and suddenly everything
worked as expected:
class WorkingSpec : FreeSpec() {
@mockk
lateinit var thing: Thing
init {
beforeTest {
MockKAnnotations.init(this)
}
"Test something"{
every { thing.name } returns "Blah"
thing.name shouldBe "Blah"
}
}
}
@ExtendWith(MockKExtension::class)
class AlsoWorkingSpec : FreeSpec() {
@mockk
lateinit var thing: Thing
init {
"Test something"{
every { thing.name } returns "Blah"
thing.name shouldBe "Blah"
}
}
}
This is either a bug or just somethin that needs documenting for newbies
like me :)
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#583 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAFVSGVSMLNL3UVC5NS55J3RMHJPLANCNFSM4GQEEVCA>
.
|
I made a gist about getting up and running with kotest and mockk if anyone stubles upon this like i did and wants some copy paste code |
Recently, in
Mockk
's slack andKotlinTest
's slack, some users have reported troubles when usingMockk
with KotlinTest, due to the mockk context not being cleared after tests.This is due to the isolation mode being incorrect for the use case, as the user normally wants the class to be instantiated once per test (
InstancePerTest
isolation).As
Mockk
is a very used mocking library for Kotlin, among other libraries, maybe we should create a specific part in the documentation for explaining this, or a paragraph in isolation mode.Users don't associate directly that the "Bug" in their mocks using KotlinTest is due to isolation mode. Usually because the default mode for JUnit is single instance per test, and we don't do that, so writing the same test "bugs" their code because of it.
What do you think, @sksamuel ?
Also summoning @oleksiyp
The text was updated successfully, but these errors were encountered: