如何在Kotlin中测试私有方法?我尝试从@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
添加androidx.annotation.VisibleForTesting
,但这并没有使我的函数私有化
这就是我的使用方式
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
fun doSomething() {}
[编辑]
我知道我不应该测试private
方法,但是它现在总是微不足道的。那下面的情况呢?
我有一个CsvReader类
class CsvReader(private val inputStream: InputStream, private val separator: String = "\t") {
fun read(): List<String> {
return read(inputStream.bufferedReader())
}
private fun read(bufferedReader: BufferedReader): List<String> {
val line = bufferedReader.use { it.readLine() } // `use` is like try-with-resources in Java
return parse(line)
}
private fun parse(line: String): List<String> {
return line.split(separator)
}
}
我为此编写了测试
class CsvReaderTest {
private val stream = mock<InputStream>()
private val reader = CsvReader(stream)
private val bufferedReader = mock<BufferedReader>()
@Test
fun read() {
whenever(bufferedReader.readLine()).thenReturn("Jakub\tSzwiec")
reader.read(bufferedReader) shouldEqual listOf("Jakub", "Szwiec")
}
@Test
fun readWhenEmpty() {
whenever(bufferedReader.readLine()).thenReturn("")
reader.read(bufferedReader) shouldEqual listOf("")
}
@Test
fun throwIOExceptionWhenReadingProblems() {
whenever(bufferedReader.readLine()).thenThrow(IOException::class.java)
val read = { reader.read(bufferedReader) }
read shouldThrow IOException::class
}
}
不幸的是,对于测试,我需要调用私有函数fun read(bufferedReader: BufferedReader): List<String>
,因为在模拟File
时,file.bufferedReader
给出了NullPointerException
Unable to mock BufferedWriter class in junit
答案 0 :(得分:3)
对此只有一个一个答案:甚至不要尝试。
您编写源代码来传达意图。如果您做某事private
,那么那是内部实现细节。下一秒可能会更改。
答案 1 :(得分:3)
像这样:
fun callPrivate(objectInstance: Any, methodName: String, vararg args: Any?): Any? {
val privateMethod: KFunction<*>? =
objectInstance::class.functions.find { t -> return@find t.name == methodName }
val argList = args.toMutableList()
(argList as ArrayList).add(0, objectInstance)
val argArr = argList.toArray()
privateMethod?.apply {
isAccessible = true
return call(*argArr)
}
?: throw NoSuchMethodException("Method $methodName does not exist in ${objectInstance::class.qualifiedName}")
return null
}
您需要传递要调用该方法的对象的实例,方法名称和必需的参数
答案 2 :(得分:1)
你可以使用java反射:
测试方法:
private fun printGreetings(name: String): String {
return "Hello, $name"
}
够了:
private val classUnderTest = spyk(ClassUnderTest())
@Test
fun `should return greetings`() {
val method = classUnderTest.javaClass.getDeclaredMethod("printGreetings", String::class.java)
method.isAccessible = true
val parameters = arrayOfNulls<Any>(1)
parameters[0] = "Piotr"
assertEquals("Hello, Piotr", method.invoke(classUnderTest, *parameters) )
}