pact-jvm
pact-jvm copied to clipboard
BaseMockServer crash with Robolectric
When executing tests in my Android test target, using Robolectric I get the following error:
`java.lang.NoSuchMethodError: org.apache.http.conn.ssl.SSLSocketFactory.
at au.com.dius.pact.consumer.BaseMockServer.waitForServer(MockHttpServer.kt:88)
at au.com.dius.pact.consumer.BaseMockServer.runAndWritePact(MockHttpServer.kt:105)
at au.com.dius.pact.consumer.ConsumerPactRunnerKt.runConsumerTest(ConsumerPactRunner.kt:13)
at au.com.dius.pact.consumer.junit.BaseProviderRule.runPactTest(BaseProviderRule.java:163)
at au.com.dius.pact.consumer.junit.BaseProviderRule.access$100(BaseProviderRule.java:27)
at au.com.dius.pact.consumer.junit.BaseProviderRule$1.evaluate(BaseProviderRule.java:83)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.robolectric.RobolectricTestRunner$HelperTestRunner$1.evaluate(RobolectricTestRunner.java:546)
at org.robolectric.internal.SandboxTestRunner$2.lambda$evaluate$0(SandboxTestRunner.java:252)
at org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread$0(Sandbox.java:89)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)`
Robolectric may be a red herring here, as I get a "method not mocked" exception when running the same tests without the robolectric test runner. Attempting to test a configured retrofit 2 client. I'm trying to add Pact testing to my existing Android project, so I don't have any issues with the unit under test.
I've checked for dependency conflicts with httpclient in the project and found none. It simply looks like the org.apache.http.conn.ssl.SSLSocketFactory
has no constructor taking TrustStrategy
Damn Android, they have different versions of the Apache HTTP libraries.
Anything we can do about it, or any workaround? I'm using Junit5 but for Robolectric to work I have to use the Junit4 Runner, which is where I run into this issue. It's looking more and more like I'll need to cut bait and find a different solution for contract testing my API clients :(
Depends if you need HTTPS or not. If not, we can just use reflection to check the SSLSocketFactory method signature and not set up the factory if it is not supported.
I had the same issue as well and here is a way to fix it:
- first, verify that you are using the latest apache HTTP library by running the following
./gradlew dependencies
- since apache http is deprecated you would need to add the following to manifest
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
https://developer.android.com/about/versions/pie/android-9.0-changes-28#apache-p
I'm having the same issue.
The workaround provided by @moetouban didn't work for me
I built a version locally without https support (Deleting the SSLSocketFactory and TrustStrategy lines) and now the MockServer starts.
Ping @uglyog is there any workaround ?
I really don't want to maintain a local fork and probably this may be blocking other people :)
(If checking if the SSLSocketFactory
is available before using it is an viable option I can provide a PR)
This is what I'm doing right now because I dont need http/SSL
diff --git a/consumer/src/main/kotlin/au/com/dius/pact/consumer/MockHttpServer.kt b/consumer/src/main/kotlin/au/com/dius/pact/consumer/MockHttpServer.kt
index 7c2b684a5..ce0a599ec 100755
--- a/consumer/src/main/kotlin/au/com/dius/pact/consumer/MockHttpServer.kt
+++ b/consumer/src/main/kotlin/au/com/dius/pact/consumer/MockHttpServer.kt
@@ -27,8 +27,6 @@ import org.apache.http.client.methods.HttpOptions
import org.apache.http.config.RegistryBuilder
import org.apache.http.conn.socket.ConnectionSocketFactory
import org.apache.http.conn.socket.PlainConnectionSocketFactory
-import org.apache.http.conn.ssl.SSLSocketFactory
-import org.apache.http.conn.ssl.TrustSelfSignedStrategy
import org.apache.http.entity.ContentType
import org.apache.http.impl.client.HttpClientBuilder
import org.apache.http.impl.conn.BasicHttpClientConnectionManager
@@ -99,14 +97,11 @@ abstract class BaseMockServer(val pact: RequestResponsePact, val config: MockPro
private val requestMatcher = RequestMatching(pact.interactions)
override fun waitForServer() {
- val sf = SSLSocketFactory(TrustSelfSignedStrategy())
val retryStrategy = CustomServiceUnavailableRetryStrategy(5, 500)
val httpclient = HttpClientBuilder.create()
.setConnectionManager(BasicHttpClientConnectionManager(RegistryBuilder.create<ConnectionSocketFactory>()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
- .register("https", sf)
.build()))
- .setSSLSocketFactory(sf)
.setServiceUnavailableRetryStrategy(retryStrategy)
.build()
@andreroggeri I don't use Roboelectric or Android, so I am unable to diagnose or test this.
A PR would be awesome.