问题描述
有些观点可以澄清,这并不是有人建议的重复问题:
- 这是由长日志标记名称引起的“ 运行时崩溃”。即
okhttp3.mockwebserver.MockWebServer
,这是不是IDE棉绒错误。 - 此崩溃是由第三方依赖性(即MockWebServer)引起的。感谢Yuri Schimke提出的错误 Fix android logging with MockWebServer。
- 我已在答案https://stackoverflow.com/a/63388805/8034839中提供了解决方案。
原始问题:
我正在使用Expresso
和MockWebServer
进行Android Web服务测试,但是遇到以下异常,该异常告诉我日志标签问题:
“ okhttp3.mockwebserver.MockWebServer”超出了23个字符的限制。
详细的堆栈跟踪如下:
2020-08-13 11:31:13.277 16901-17085/com.xxx.app I/okhttp.OkHttpClient: <-- HTTP FAILED: java.net.SocketTimeoutException: timeout
2020-08-13 11:31:13.280 16901-17346/com.xxx.app E/AndroidRuntime: FATAL EXCEPTION: MockWebServer TaskRunner
Process: com.xxx.app,PID: 16901
java.lang.IllegalArgumentException: Log tag "okhttp3.mockwebserver.MockWebServer" exceeds limit of 23 characters
at android.util.Log.isLoggable(Native Method)
at okhttp3.internal.platform.android.AndroidLog.androidLog$okhttp(AndroidLog.kt:66)
at okhttp3.internal.platform.android.AndroidLogHandler.publish(AndroidLog.kt:39)
at java.util.logging.Logger.log(Logger.java:615)
at java.util.logging.Logger.doLog(Logger.java:636)
at java.util.logging.Logger.log(Logger.java:725)
at okhttp3.mockwebserver.MockWebServer$serveConnection$$inlined$execute$1.runOnce(TaskQueue.kt:224)
at okhttp3.internal.concurrent.TaskRunner.runTask(TaskRunner.kt:116)
at okhttp3.internal.concurrent.TaskRunner.access$runTask(TaskRunner.kt:42)
at okhttp3.internal.concurrent.TaskRunner$runnable$1.run(TaskRunner.kt:65)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:762)
2020-08-13 11:31:13.293 16901-17346/com.xxx.app I/Process: Sending signal. PID: 16901 SIG: 9
解决方法
在深入研究MockWebServer.kt
的源代码之后,我已经找到了解决此问题的方法。在此文件中,有一个如下所示的属性:
private val logger = Logger.getLogger(MockWebServer::class.java.name)
MockWebServer::class.java.name
将返回完整的类名okhttp3.mockwebserver.MockWebServer
,显然,此名称作为Android日志标签已超过23个字符。该修复程序使用Kotlin反射来替换logger属性。反射代码如下:
fun <T : Any> T.setPrivateProperty(variableName: String,data: Any): Any? {
return javaClass.getDeclaredField(variableName).let { field ->
field.isAccessible = true
field.set(this,data)
return@let field.get(this)
}
}
在@before
方法内,使用simpleName
设置记录器标签
val mockWebServer = MockWebServer() // this is declared inside test class.
@Before
fun setup() {
mockWebServer.setAndReturnPrivateProperty("logger",Logger.getLogger(MockWebServer::class.java.simpleName))
mockWebServer.start(8080)
}
MockWebServer::class.java.simpleName
将返回较短的类名并解决该问题。
这是由于Log API不允许标签超过23个字符。
您可以按照Terence's answer禁用棉绒检查,但已收到警告。
为更好地理解,请访问: The logging tag can be at most 23 characters