2016-02-29 22 views
5

在改进1.x中,我使用以下模式创建模拟某些构建变体的错误网络连接的api服务类。模拟使用改进2的错误网络(在实际的,即非模拟的API上)

// Retrofit 1 
private <T> T create(Class<T> apiServiceClass) { 
    T apiService = restAdapter.create(apiServiceClass); 
    if (!BuildConfig.IS_PRODUCTION_BUILD) { 
     endpoints = mockRestAdapter.create(apiServiceClass, apiService); 
    } 
    return apiService; 
} 

这很酷的事情是,我的实际API端点被使用。这样我就可以看到应用程序在片状连接上的行为,而且我不需要提供模拟/人工响应。

现在,在改造2中,对于MockRestAdapter或更确切地说MockRetrofit的API完全改变。 MockRetrofit#create现在返回BehaviorDelegate。如果我尝试使用与之前相同的图案

// Retrofit 2 
private <T> T create(Class<T> apiServiceClass) { 
    T apiService = retrofit.create(apiServiceClass); 
    if (!BuildConfig.IS_PRODUCTION_BUILD) { 
     endpoints = mockRetrofit.create(apiServiceClass).returning(???); 
    } 
    return apiService; 
} 

我卡在returning(???)上。 returning预计执行Call<?>。但我似乎无法弄清楚如何实现它,使其像我的Retrofit 1示例一样工作(也许它不打算)。

所以我的问题是:一般来说,我如何才能实现上述Retrofit 1模式来模拟实际的API与改造2上的不良网络?

回答

6

最终我想通了。这个想法是使用OkHttp的应用程序拦截器。这是解决方案。

首先,创建一个NetworkBehavior

final NetworkBehavior behavior = NetworkBehavior.create(); 
behavior.setDelay(2000, TimeUnit.MILLISECONDS); 
behavior.setFailurePercent(50); 
behavior.setVariancePercent(50); 

当然,你可以提供给behavior UI组件动态地改变这些值。

当配置OkHttpClient添加下面的拦截器。

final OkHttpClient.Builder builder = new OkHttpClient.Builder(); 
if (!BuildConfig.IS_PRODUCTION_BUILD) { 
    builder.addInterceptor(new HttpLoggingInterceptor()); 
    builder.addInterceptor(new Interceptor() { 
     @Override public Response intercept(Chain chain) throws IOException { 
      try { 
       Thread.sleep(behavior.calculateDelay(TimeUnit.MILLISECONDS)); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      if (behavior.calculateIsFailure()) { 
       return new Response.Builder() 
         .code(500) 
         .message("MockError") 
         .protocol(Protocol.HTTP_1_1) 
         .request(chain.request()) 
         .body(ResponseBody.create(MediaType.parse("text/plain"), "MockError")) 
         .build(); 
      } 
      return chain.proceed(chain.request()); 
     } 
    }); 
} 

请注意,您应该前添加一个日志记录拦截使请求日志正常显示。手动创建的响应对象当然可以根据自己的喜好进行调整。有些值是强制性的(例如或request)。如果您不指定它们,您将收到NPE。实际上,同样的方法也适用于改装1.

+1

正是我所搜索的。谢谢! – user1795683

+1

首先感谢您的回答。我也希望用'MockRetrofit'来解决这个问题。我最终做了类似于你的事情。但是如果你使用'OkHttp''Interceptor'来代替自己,你可以编写你自己的'NetworkBehavior'类来完成你所需要的。否则,你只能依靠整个'retrofit-mock'库来在一个类中使用两种方法。 – tir38

+0

build.gradle中的依赖关系是'compile'c​​om.squareup.retrofit2:retrofit-mock:2.3.0''(版本2.3.0当前) –