Okhttp: PowerMock and MockWebServer do not play well together

Created on 18 May 2017  路  9Comments  路  Source: square/okhttp

This is with mockwebserver 3.4.1, powermock 1.5.1 and Kotlin 1.1.0. This is the test:

@RunWith(PowerMockRunner::class)
@PrepareForTest(String::class)
class MyTest {
    companion object {
        private val server = MockWebServer().apply { start() }

        @AfterClass
        fun tearDown(){
            server.shutdown()
        }
    }

    @Test
    fun someTest(){
    }
}

Which results in:

Exception in thread "main" java.lang.AssertionError
    at okhttp3.OkHttpClient.systemDefaultTrustManager(OkHttpClient.java:260)
    at okhttp3.OkHttpClient.<init>(OkHttpClient.java:228)
    at okhttp3.OkHttpClient.<init>(OkHttpClient.java:203)
    at okhttp3.internal.Internal.initializeInstanceForTests(Internal.java:41)
    at okhttp3.mockwebserver.MockWebServer.<clinit>(MockWebServer.java:104)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at javassist.runtime.Desc.getClassObject(Desc.java:43)
    at javassist.runtime.Desc.getClassType(Desc.java:152)
    at javassist.runtime.Desc.getType(Desc.java:122)
    at javassist.runtime.Desc.getType(Desc.java:78)
    at com.mycompany.MyTest.<clinit>(MyTest.kt:30)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.createTestInstance(PowerMockJUnit44RunnerDelegateImpl.java:186)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.createTest(PowerMockJUnit44RunnerDelegateImpl.java:171)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:193)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
    at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:33)
    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:118)
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:101)
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
    at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

Most helpful comment

try adding this @PowerMockIgnore("javax.net.ssl.*")

All 9 comments

Please report this issue to the PowerMock maintainers. That library goes out of its way to defeat encapsulation and instability is the cost of that.

@swankjesse could you tell what is wrong and have to be fixed on PowerMock side? What is a reason of the assertion error?

Stab in the dark - try this https://stackoverflow.com/a/36167978/1542667

And raise a bug with the powermock library if it persists

@yschimke, I'm sorry for possible misunderstanding. I'm PowerMock maintainer and the issue for PowerMock has been created. To fix an issue on PowerMock side I need to know what is wrong and have to fixed. The exception is not informative. Why it could be thrown?

@thekingnothing It is some subclass of GeneralSecurityException. Almost certainly NoSuchAlgorithmException from TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()). This shouldn't be possible in a valid JVM. Hence the pushback onto your project.

n.b. We landed a change to make it easier for users to debug these sorts of issues, should help in future https://github.com/square/okhttp/pull/3541

  private X509TrustManager systemDefaultTrustManager() {
    try {
      TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
          TrustManagerFactory.getDefaultAlgorithm());
      trustManagerFactory.init((KeyStore) null);
      TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
      if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
        throw new IllegalStateException("Unexpected default trust managers:"
            + Arrays.toString(trustManagers));
      }
      return (X509TrustManager) trustManagers[0];
    } catch (GeneralSecurityException e) {
      throw assertionError("No System TLS", e); // The system has no TLS. Just give up.
    }
  }

@thekingnothing this code is supposed to return normally. With PowerMock, it doesn鈥檛.

  private X509TrustManager systemDefaultTrustManager() {
    try {
      TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
          TrustManagerFactory.getDefaultAlgorithm());
      trustManagerFactory.init((KeyStore) null);
      TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
      if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
        throw new IllegalStateException("Unexpected default trust managers:"
            + Arrays.toString(trustManagers));
      }
      return (X509TrustManager) trustManagers[0];
    } catch (GeneralSecurityException e) {
      throw assertionError("No System TLS", e); // The system has no TLS. Just give up.
    }
  }

In case this is of any help this is easily solved (thanks to @thekingnothing ) using PowerMockIgnore. See powermock/powermock#810.

Ohh, thank you @jonyt for clue. It was just guessing, but I'm happy that it helped you.

I think main cause of the issue it's either classcastexception or linkerror

Thank all for information. I understand more now, I'll try to find a way to fix it.

While workaround with 'PowerMockIgnore` could be used.

try adding this @PowerMockIgnore("javax.net.ssl.*")

Was this page helpful?
0 / 5 - 0 ratings

Related issues

albka1986 picture albka1986  路  3Comments

sargunv picture sargunv  路  3Comments

nikunjgundaniya picture nikunjgundaniya  路  3Comments

vanshg picture vanshg  路  3Comments

yschimke picture yschimke  路  3Comments