这是测试的方法:
它获取一个 URL 并在发送 GET 请求后返回一个 json。它是一个普通函数,位于包中,而不是类中的方法。下面的扩展方法也是如此。
fun getJson (url: String): String {
val connection = URL(url).openConnection() as HttpURLConnection
connection.requestMethod = "GET"
return connection.getResult()
}
这是扩展方法:
它将开始连接并从结果流中读取。
internal fun HttpURLConnection.getResult(charset: Charset = Charsets.UTF_8): String {
this.connect()
return this.inputStream.bufferedReader(charset).use { it.readText() }
}
这是测试用例:
我试图模拟即将在这里使用的HttpURLConnection
并调用原始方法,然后只需调用该方法并断言模拟是否已设置了预期值。
class Spike {
@Test
fun test_getJson() {
val expectedResult = "{ok: true}"
val mockConnection = mock(HttpURLConnection::class.java)
Mockito.`when`(mockConnection.getResult()).thenReturn(expectedResult)
getJson("http://www.google.com")
assertEquals("GET", mockConnection.requestMethod)
assertEquals("http://www.google.com", mockConnection.url.host)
}
}
这是错误
java.lang.IllegalStateException: this.inputStream 不得为 null at my.spike.pack.http.UtilsKt.getResult(utils.kt:45(
就像模拟不起作用一样。
如何在不更改getJson
函数签名的情况下解决此问题?
由于 Kotlin 扩展方法在类/字节码级别实现的方式,这将不起作用。
您在源代码中看到的是HttpURLConnection.getResult
但是在类/字节码级别,使用静态方法创建了另一个文件:public final static getResult(HttpURLConnection, Charset)
。
Mockito不能模拟静态方法。如果你真的要模拟一个,那么我认为PowerMock有能力做到这一点。
编辑:如果你有一个模块范围的函数,那么它也会在类上生成。假设您有一个带有函数的文件StreamFunctions.kt
:doSomething
,那么(默认情况下(将生成带有静态函数doSomething
的类StreamFunctionsKt
。更多细节可以在这里找到:https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html
这应该像
Mockito.`when`(mockConnection.inputStream).thenReturn(ByteArrayInputStream("test".toByteArray()))