首页 > 解决方案 > Mockk,如何模拟在私有函数中使用的 JSONObject 构造函数

问题描述

使用 mockk,testImplementation "io.mockk:mockk:1.9.3"

有一个MetaData通过 api 构建的类fun from(intent: Intent?): MetaData?

class MetaData {

    @JvmField
    val rid: String
    ......

   private constructor(meta: JSONObject) {
        rid = meta.optString("RID", "")
    }

   companion object {

        @JvmStatic
        fun from(intent: Intent?): MetaData? {
            if (intent == null) {
                 return null
            }

            val metaJsonStr: String = intent.getStringExtra("meta") ?: return null
                   
            val rmeta = getMetaDataJson(metaJsonStr)
                ?: return null
                     
            return MetaData(meta)
        }
        
        private fun getMetaDataJson(json: String): JSONObject? {
            
            return try {
                JSONObject(json)
            } catch (e: JSONException) {
                System.out.println("+++ !!! 111 exp in getMetaDataJson(), $e")
                null
            } catch (e: NullPointerException) {
                System.out.println("+++ !!! 222 exp in getMetaDataJson(), $e")
                null
            }
        }
    }
}

想测试抛出JSONException和的代码路径NullPointerException

已经尝试过这个测试,它可以测试空路径intent.getStringExtra("meta")

@Test
    fun test_from_WhenCalledWithIntentWithNometa_ShouldReturnNull() {
        val intentMock: Intent = mockk<Intent>(relaxed = true)
        every { intentMock.getStringExtra(any()) } returns null
        val metaData = MetaData.from(intentMock)
        Assert.assertEquals(metaData, null)
    }

如何使这个测试进入getMetaDataJson(json),我想不需要模拟 Intent 而是 JSONObject 构造函数(如何)?

或者是否可以存根,fun getMetaDataJson(json: String)但无论输入是什么,它都应该将输入json字符串替换为一些配置的测试数据?

如何测试两个异常路径?

标签: androidunit-testingkotlinmockk

解决方案


/**
 * Creates a new {@code JSONObject} with name/value mappings from the JSON
 * string.
 *
 * @param json a JSON-encoded string containing an object.
 * @throws JSONException if the parse fails or doesn't yield a {@code
 *     JSONObject}.
 */
public JSONObject(@NonNull String json) throws JSONException {
    this(new JSONTokener(json));
}

如果传递的字符串无效,JSONObject 构造将引发异常。只需传递一个随机字符串"This random: String",你应该得到JSONException.

关于NullPointerException你不应该注意这个异常,因为构造函数不会抛出它。


推荐阅读