Kotlin JUnit 4测试中无法捕获异常的问题求助
单元测试校验JSON合法性时异常未捕获的问题解决
我懂你现在的困扰——本来想靠创建JSONObject/JSONArray加捕获异常的方式,来校验字符串是不是合法JSON,结果运行测试时异常根本没被触发,完全不符合预期。咱们来一步步拆解问题,找到解决办法。
先说说你的代码里可能藏的坑
你的测试代码是这样的:
@Test fun checkFunctionWithStringToJSONTest() { val invalidJSON = "INVALIDJSON--" try { JSONObject(invalidJSON) } catch (ex: Exception) { try { JSONArray(invalidJSON) } catch (ex1: Exception) { assert(false) } } assert(true) }
这里可能出问题的地方有这几个:
1. 用错了JSON库
这是最常见的原因!如果你用的是Gson的JsonObject而不是Android原生的org.json.JSONObject,那直接传字符串给构造器根本不会触发解析——Gson的JsonObject构造器是空的,根本不处理字符串,自然不会抛异常。这种情况下,你得用Gson的解析方法才会触发错误。
2. 异常捕获和断言逻辑不够严谨
就算用的是Android原生库,泛泛地捕获Exception虽然能覆盖JSONException,但你的断言逻辑有点绕:只有当两种解析都失败时才会assert(false),否则直接走到assert(true)。如果你的测试用例是无效JSON,那预期应该是测试失败,但如果异常没被捕获,说明库的解析逻辑出了问题——但"INVALIDJSON--"这种字符串绝对不可能被合法解析,所以还是大概率库用错了。
给你两种场景下的修正方案
场景1:用Android原生org.json库
这种情况下,咱们明确捕获JSONException,同时把逻辑理得更清晰,测试失败时还能给出明确提示:
import org.json.JSONArray import org.json.JSONException import org.json.JSONObject import org.junit.Test import kotlin.test.assertFalse import kotlin.test.assertTrue // 测试无效JSON的情况 @Test fun invalidJSONShouldBeRejected() { val invalidJSON = "INVALIDJSON--" var isJSONValid = false try { // 先尝试解析为JSON对象 JSONObject(invalidJSON) isJSONValid = true } catch (ex: JSONException) { try { // 对象解析失败,尝试解析为JSON数组 JSONArray(invalidJSON) isJSONValid = true } catch (ex1: JSONException) { // 两种都失败,说明不是合法JSON isJSONValid = false } } // 无效JSON预期是false,断言失败时会显示提示语 assertFalse(isJSONValid, "该字符串不是合法的JSON格式") } // 测试合法JSON的情况,确保逻辑正确 @Test fun validJSONShouldBeAccepted() { val validJSONObject = "{\"name\":\"test\"}" val validJSONArray = "[1,2,3]" // 校验合法JSON对象 var isJSONValid = false try { JSONObject(validJSONObject) isJSONValid = true } catch (ex: JSONException) { try { JSONArray(validJSONObject) isJSONValid = true } catch (ex1: JSONException) { isJSONValid = false } } assertTrue(isJSONValid, "合法JSON对象应该被正确识别") // 校验合法JSON数组 isJSONValid = false try { JSONObject(validJSONArray) isJSONValid = true } catch (ex: JSONException) { try { JSONArray(validJSONArray) isJSONValid = true } catch (ex1: JSONException) { isJSONValid = false } } assertTrue(isJSONValid, "合法JSON数组应该被正确识别") }
场景2:用Gson库
如果是用Gson,就得用它的fromJson方法来触发解析,而不是直接构造JsonObject:
import com.google.gson.Gson import com.google.gson.JsonSyntaxException import org.junit.Test import kotlin.test.assertFalse import kotlin.test.assertTrue @Test fun checkJSONValidityWithGson() { val invalidJSON = "INVALIDJSON--" val validJSON = "{\"key\":\"value\"}" val gson = Gson() // 测试无效JSON var isJSONValid = false try { // 用Any类型可以同时兼容对象和数组 gson.fromJson(invalidJSON, Any::class.java) isJSONValid = true } catch (ex: JsonSyntaxException) { isJSONValid = false } assertFalse(isJSONValid, "无效字符串应该被识别为非JSON") // 测试有效JSON isJSONValid = false try { gson.fromJson(validJSON, Any::class.java) isJSONValid = true } catch (ex: JsonSyntaxException) { isJSONValid = false } assertTrue(isJSONValid, "合法JSON应该被正确识别") }
额外的小建议
可以把校验JSON合法性的逻辑抽成一个单独的工具函数,比如:
fun isJSONValid(str: String): Boolean { return try { JSONObject(str) true } catch (ex: JSONException) { try { JSONArray(str) true } catch (ex1: JSONException) { false } } }
这样测试代码会更简洁,而且这个函数还能在其他业务逻辑里复用。
内容的提问来源于stack exchange,提问作者RWIL
相关产品推荐
相关产品推荐

