2016-06-27 2 views
4

Я пытаюсь выполнить тестирование некоторых вызовов API с помощью MockWebServer и Robolectric.Использование MockWebServer с Robolectric

Моего тестовый класс с аннотацией:

@RunWith(RobolectricGradleTestRunner.class) 
@Config(constants = BuildConfig.class, sdk = 23) 

Однако при попытке построить экземпляр Дооснащаемого я получаю следующее исключение:

java.lang.NullPointerException 
    at android.os.Handler.__constructor__(Handler.java:229) 
    at android.os.Handler.<init>(Handler.java) 
    at retrofit2.Platform$Android$MainThreadExecutor.<init>(Platform.java:105) 
    at retrofit2.Platform$Android.defaultCallbackExecutor(Platform.java:97) 
    at retrofit2.Retrofit$Builder.build(Retrofit.java:556) 

кода я использую для создания экземпляра модифицированного :

Retrofit retrofit = new Retrofit.Builder() 
       .baseUrl(mMockServer.url("")) 
       .addConverterFactory(GsonConverterFactory.create()) 
       .build(); 

Исключение, указанное выше, возвращается по телефону .build().

Как исправить эту проблему?

ответ

3

У меня была эта проблема. Существует ошибка об основной причине here, но пока это продолжается, я решил использовать Robolectric 3.0 и решение, описанное dave-r12 here, которое должно создать макет, который я привел ниже.

@RunWith(RobolectricGradleTestRunner.class) 
@Config(shadows = CreateOkHttpClientTest.MyNetworkSecurityPolicy.class) 
public class CreateOkHttpClientTest { 

    @Test 
    ... 

    @Implements(NetworkSecurityPolicy.class) 
    public static class MyNetworkSecurityPolicy { 

     @Implementation 
     public static NetworkSecurityPolicy getInstance() { 
      try { 
       Class<?> shadow = MyNetworkSecurityPolicy.class.forName("android.security.NetworkSecurityPolicy"); 
       return (NetworkSecurityPolicy) shadow.newInstance(); 
      } catch (Exception e) { 
       throw new AssertionError(); 
      } 
     } 

     @Implementation 
     public boolean isCleartextTrafficPermitted() { 
      return true; 
     } 
    } 

} 
+1

Я не совсем уверен, почему, но это работает! Спасибо! – tofiffe

0

Не могли бы вы попытаться использовать sdk = 21. Я считаю, что поддержка sdk = 23 была добавлена ​​только из версии 3.1-SNAPSHOT и не выпускалась.

Edit: я неправильно была добавлена ​​поддержка с версии 3.1, потому что я мог бы успешно провести тест

@RunWith(RobolectricGradleTestRunner.class) 
@Config(constants = BuildConfig.class, sdk = 23) 
public class ExampleUnitTest { 

private MockWebServer mMockServer = new MockWebServer(); 

    @Test 
    public void build_retrofit() throws Exception { 
     Retrofit retrofit = new Retrofit.Builder() 
       .baseUrl(mMockServer.url("")) 
       .addConverterFactory(GsonConverterFactory.create()) 
       .build(); 

    } 
} 

Мой gradle.build

testCompile 'junit:junit:4.12' 
testCompile "org.robolectric:robolectric:3.1" 
testCompile 'com.squareup.okhttp3:mockwebserver:3.3.0' 

compile 'com.squareup.retrofit2:retrofit:2.1.0' 
compile 'com.squareup.retrofit2:converter-gson:2.1.0' 

какие библиотеки версии вы используете?

+0

Просто пробовал, по-видимому, это делает никакой разницы – tofiffe

+0

я не мог запустить тест без ошибок '@RunWith (RobolectricGradleTestRunner.class) @Config (константы = BuildConfig.class, SDk = 23) общественного класса ExampleUnitTest { частный MockWebServer mMockServer = новый MockWebServer(); @Test общественный недействительный addition_isCorrect() бросает исключение { Дооснащаемого переоснащения = новый Retrofit.Builder() .baseUrl (mMockServer.url ("")) .addConverterFactory (GsonConverterFactory.create()) .построить(); } } ' –

0

Альтернативное решение, которое, кажется, работает, чтобы просто обеспечить фиктивный исполнителем при настройке Дооснащение

Retrofit retrofit = new Retrofit.Builder() 
      .baseUrl("http://www.example.com/") 
      .client(client) 
      .callbackExecutor(new Executor() { 
       @Override 
       public void execute(Runnable command) { 
        //doesn't matter since tests are synchronous 
       } 
      }) 
      .addConverterFactory(ScalarsConverterFactory.create()) 
      .build(); 

Это может быть что-то, что в конце концов должно быть исправлено на стороне Retrofit, как-то обнаруживая, является ли текущая платформа Robolectric и возвращает фиктивный исполнитель или что-то в этом роде.

0

Если вы застряли на Robolectric 3 или ниже, и вы ориентируетесь на API 25, то правильное решение почти такое же, как и принятое.

@Implements(NetworkSecurityPolicy.class) 
public class NetworkSecurityPolicyShadow { 

    @Implementation 
    public static NetworkSecurityPolicy getInstance() { 
     try { 
      Class<?> shadow = Class.forName("android.security.NetworkSecurityPolicy"); 
      return (NetworkSecurityPolicy) shadow.newInstance(); 
     } catch (Exception e) { 
      throw new AssertionError(); 
     } 
    } 

    @Implementation 
    public boolean isCleartextTrafficPermitted(String host) { 
     return true; 
    } 
} 

Только разница в isCleartextTrafficPermitted(String host) потому что OkHttp попытается вызвать этот метод с host аргументом.

Смежные вопросы