使用 Retrofit 和 MockWebServer 模拟无网络
Posted
技术标签:
【中文标题】使用 Retrofit 和 MockWebServer 模拟无网络【英文标题】:Simulate no network using Retrofit and MockWebServer 【发布时间】:2014-09-17 02:50:24 【问题描述】:我想模拟使用RetroFit
和MockWebServer
时的无网络情况。
我目前正在使用Espresso
进行测试,并在开始测试之前将MockWebServer
s url 提供给RestAdapter
。这对于模拟服务器响应等非常有用,但我看不到一种简单的方法来编写当设备没有网络时抛出的java.net.ConnectException
异常。我可以看到 MockResponse 允许限制模拟等,但不是自定义异常。
我知道我可以从根本上模拟 retrofit
使用的实际 Web api 接口,但如果可能的话,我想使用与其他测试相同的方法,使用 MockWebServer
。
我想我只是错过了一些简单的事情:)
谢谢
【问题讨论】:
【参考方案1】:Retrofit 有一个 retrofit-mock
模块,它提供了一个 MockRestAdapter
类,其目的是模拟网络延迟和错误。
这是一个与普通RestAdapter
一起使用来创建服务实例的方法。您可以在 repo 的 samples/mock-github-client/
文件夹中看到完整示例:https://github.com/square/retrofit/tree/parent-1.9.0/retrofit-samples/mock-github-client
MockRestAdapter
提供这些 API:
setDelay
- 设置网络往返延迟,以毫秒为单位。
setVariancePercentage
- 设置网络往返延迟的正负方差百分比。
setErrorPercentage
- 设置对calculateIsFailure()
的调用百分比,返回true
。
在您的测试中,您可以致电setErrorPercentage(100)
以保证会发生网络错误。默认情况下,抛出错误的时间是延迟的 0 到 3 倍。将延迟设置为 0 以获得即时结果。
【讨论】:
链接坏了:( 更新链接:github.com/square/retrofit/blob/master/retrofit-mock/src/test/… 先生,我尝试将改造的 baseurl 覆盖为来自 mockwebserver 的那个,但是在执行测试时我仍然最终会调用 webservice,有没有办法阻止它?请协助。 @tony19,杰克·沃顿【参考方案2】:使用 MockWebServer 模拟网络问题的最简单方法是将 SocketPolicy 设置为 SocketPolicy.DISCONNECT_AT_START、SocketPolicy.NO_RESPONSE 等:
MockWebServer server = new MockWebServer();
MockResponse response = new MockResponse()
.setSocketPolicy(SocketPolicy.DISCONNECT_AT_START);
server.enqueue(response);
通过这种方式,您可以模拟网络错误,例如连接在响应之前过早关闭或超时异常
【讨论】:
【参考方案3】:要清楚这里的异常类型,您可以看到不同之处:
Internet Connection Error
所以你可以得到两种类型:
UnknownHostException - 当您没有互联网或未知主机时...为了模拟这种情况,请为适配器设置一个不正确的端点。
ConnectException - mockwebserver 可以抛出超时异常。您可以在此处查看操作方法:
https://github.com/square/okhttp/tree/master/mockwebserver
我真的不知道你的代码是怎样的,但我希望这很有用
【讨论】:
+1 感谢您的回答,但它并没有真正回答问题,因为我想模拟没有网络而不是超时。调度员很有趣。我想知道我是否可以抛出上述异常...... 似乎我无法检查网络异常,并且调度程序仅根据其接口抛出 Inturrupted【参考方案4】:不知道有没有用,不过可以用 MockWebServer 模拟超时:
String contentType = "Content-type: application/json";
MockResponse response = MockResponse().setResponseCode(statusCode).setBody(responseBody).addHeader(contentType);
MockWebServer proxy = new MockWebServer();
proxy.enqueue(response);
proxy.setBodyDelayTimeMs(timeoutDelay));
proxy.play(10000); //Number port - Important!!!
注意:请将您的代码(例如 AsyncHttpClient)的 HttpClient 设置为该端口以进行测试。
【讨论】:
【参考方案5】:对我有用的是将改造 URL(端点)指向一个随机的不存在的主机。 我使用“thisIsARandomHost.com”和宾果游戏,我能够模拟未知主机异常。
例如:setAPP_URL = "http://thisIsARandomHost.com/";
在这里,setAPP_URL 是包含我传递给改造的 url 的字符串变量,当我想在测试中模拟未知主机异常时,我将 url 设置为如上。对于所有其他目的,它被设置为有效的 URL我的应用需要。
如上述答案所述,MockWebServer 是一个用于模拟改造响应的出色库,但您不需要该库来模拟此异常。对于模拟所有其他异常,我会推荐 MockWebServer ,我在我的项目中经常使用它来测试响应。
注意:您可以将应用网址设置为任何内容,只要该网址在网络上不存在即可。
【讨论】:
【参考方案6】:mockWebServer.shutdown()
在执行单元测试之前没问题。
它在内部关闭套接字连接:
serverSocket!!.close()
【讨论】:
以上是关于使用 Retrofit 和 MockWebServer 模拟无网络的主要内容,如果未能解决你的问题,请参考以下文章
Android 网络框架 Retrofit2.0介绍使用和封装