如何测试在 Kotlin 中调用顶级函数的代码?

How to test code that calls top level functions in Kotlin?

我对 Kotlin 很陌生。

我有一个 class 调用顶级函数(进行 http 调用)。我正在尝试为我的 class 编写单元测试,而无需它进入网络。

有没有办法 mock/powermock/intercept 从我的 class 调用 Kotlin 顶级函数?

class MyClass {
    fun someMethod() {
        // do some stuff
        "http://somedomain.com/some-rest/action".httpGet(asList("someKey" to "someValue")).responseString { (request, response, result) ->
            // some processing code
        }
    }
}

正在使用 kittinunf/Fuel library 进行 httpGet 调用。

它向 String 添加了一个顶级函数,最终调用 Fuel 中的伴随对象函数 (Fuel.get())。

单元测试需要拦截对 httpGet 的调用,以便我可以 return 一个 json 字符串用于测试。

我鼓励您将远程 API 调用封装在一个接口后面,该接口将通过构造函数注入到 class 使用它:

class ResponseDto
interface SomeRest {
    fun action(data:Map<String,Any?>): ((ResponseDto)->Unit)->Unit
}
class FuelTests(val someRest: SomeRest) {
    fun callHttp(){
        someRest.action(mapOf("question" to "answer")).invoke { it:ResponseDto ->
            // do something with response 
        }
    }
}

另一种方法是注入一个假 ClientFuel:

使用
FuelManager.instance.client = object: Client {
    override fun executeRequest(request: Request): Response {
        return Response().apply {
            url = request.url
            httpStatusCode = 201
        }
    }
}

Fuel.testMode()

"http://somedomain.com/some-rest/action".httpGet(listOf()).responseString { request, response, result ->
    print(response.httpStatusCode) // prints 201
}

看来"top level functions"可以看做变相的静态方法

从这个角度来看,更好的答案是:不要以这种方式使用它们。这会导致高度直接的耦合;并使您的代码更难测试。您肯定想创建一些接口 Service,您的所有对象都应该使用该接口;然后使用依赖注入为您的客户端代码配备一些实现 Service 接口的对象。

这样做,您也完全摆脱了对 Powermock 的要求。