square / okhttp

Square’s meticulous HTTP client for the JVM, Android, and GraalVM.
https://square.github.io/okhttp/
Apache License 2.0
45.85k stars 9.16k forks source link

ParameterResolutionException when trying to use MockWebServer in JUnit 5 test case with Kotlin 1.6 #7466

Closed gregor-tset closed 1 year ago

gregor-tset commented 2 years ago

I have a simple test for an external API and want to use the MockWebServer to save some mocking I'd have to do with e.g. WireMock. However, regardless of which approach I try, I cannot get it to work.

My setup is OpenJDK Temurin-17.0.4.1+1 and Kotlin 1.6.10 - on MacOS 12.6 (21G115) with IntelliJ 2022.2.2 Ultimate (fwiw).

I have this:

class TokenRefreshServiceTest(private val server: MockWebServer) {
...
@Test
    fun getValidTokenHasAllFieldsInCorrectForm() {
    }
}

But when running the test, I get this error:

org.junit.jupiter.api.extension.ParameterResolutionException: No ParameterResolver registered for parameter [mockwebserver3.MockWebServer server] in constructor [public com.bla.blup.TokenRefreshServiceTest(mockwebserver3.MockWebServer)].

Should work according to the docs: https://github.com/square/okhttp/tree/parent-5.0.0-alpha.10/mockwebserver-junit5

I tried different dependencies:

Before that, I tried using the traditional method with a setup() method in @BeforeAll, but that requires the use of @JavaStatic in Kotlin and I ran into this funny error here: https://github.com/square/okhttp/issues/5818

So I suppose it's a bug in okhttp/MockWebServer. And yes, it was a funny afternoon...

yschimke commented 2 years ago

I'll look into it, seems like a bug that the extension isn't registered correctly. For now add

@ExtendWith(MockWebServerExtension::class)

It's changing again in alpha11, see https://github.com/square/okhttp/pull/7392 and https://github.com/square/okhttp/issues/7146

So constructors will not be supported because of junit 5 lifecycle design. Basically pass in the server in the setup method.

https://github.com/square/okhttp/pull/7392/files#diff-1e4a02b67e534461133c007db45b6cd1c0fbcfae6953bf2ebd06fad8424cdacd

gregor-tset commented 2 years ago

thanks for the analysis and explanation! Unfortunately, I now hit the same error I got myself when using a static setup method in Kotlin with MockWebServer, but now inside the library:

java.lang.NoSuchFieldError: Companion
    at okhttp3.internal._UtilCommonKt.<clinit>(-UtilCommon.kt:51)
    at okhttp3.internal._UtilJvmKt.<clinit>(-UtilJvm.kt:48)
    at mockwebserver3.MockWebServer.<init>(MockWebServer.kt:100)
    at mockwebserver3.junit5.internal.MockWebServerExtension$Resource.newServer(MockWebServerExtension.kt:50)
    at mockwebserver3.junit5.internal.MockWebServerExtension.resolveParameter(MockWebServerExtension.kt:84)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.resolveParameter(ExecutableInvoker.java:216)
yschimke commented 2 years ago

This is usually mixing different versions of mockwebserver and okhttp. Make sure that you only have a single consistent version in your project.

gregor-tset commented 2 years ago

I also read that in #5818 - and you're right, we really draw in an older version through a transitive dependency (kubernetes-client). Nothing I can change right now, but will fix during next maintenance/dependency updates.

yschimke commented 1 year ago

Nothing more to do.