Add helper to mock module-level extension functions#586
Add helper to mock module-level extension functions#586jselbo wants to merge 3 commits intomockito:mainfrom
Conversation
Top-level Kotlin extension functions compile to static methods in a *Kt class. mockExtensionFun() simplifies creating a MockedStatic for them by extracting the declaring class from a KFunction reference. Includes validation that the provided function reference is actually an extension function via KParameter.Kind.EXTENSION_RECEIVER.
The tests project is an included build, so its spotlessApply was not invoked when running spotlessApply from the root. Register a root-level task that depends on the included tests build's spotlessApply.
hick209
left a comment
There was a problem hiding this comment.
Overall this LGTM.
I just have one clarifying question.
I think we should update the kdoc and tests to make that clear for other people as well, which is the sole reason I request changes here.
| * | ||
| * val ref: KFunction2<String, String, Boolean> = String::isHello | ||
| * mockExtensionFun(ref).use { | ||
| * whenever("test".isHello("sad")).thenReturn(true) |
There was a problem hiding this comment.
I know this is like a static method extension as that's what those basically are for the JVM.
My question here is, does here mean that the input params, including the receiver, have to match?
In other words, does "anotherTest".isHello("sad") return false?
If so, I wonder if we could come up with an elegant way to do something like whenever(any<String>.isHello(mood)).thenReturn(true)
There was a problem hiding this comment.
Great question. this is equivalent to doing
whenever(ref.invoke("test", "sad")).thenReturn(true)
so I tested and surprisingly yes we can use matchers in just the same way, even with the regular function invoke syntax.
whenever(any<String>().isHello(eq("sad")).thenReturn(true)
which reads kind of weird.
But you still have to follow the rule of all args being matchers. I think for that reason, we should encourage usage of this API with the explicit f.invoke because it makes the stubbing more like traditional stubbing syntax. I will update the docs and tests to reflect this.
There was a problem hiding this comment.
Actually, the .invoke() syntax with matchers won't work because the compiled code for KFunction.invoke includes null checks that matchers can't satisfy unfortunately.
…d because I think it is a niche case that doesn't add much value
Kotlin lang ref: https://kotlinlang.org/docs/extensions.html
New syntax sugar feature: a helper to mock non-member extension functions.
Note the implementation is just
mockStaticon the declaringFooKtclass, so all declared extension functions would be mocked at the same time. There's no way to mock only one of the extension funs.Also update the spotless task so you don't need to include
:tests:spotlessApply