我想用 Kotlin 写一个 Spek 测试。
如何从
src/test/resources
文件夹中读取 HTML 文件?
class MySpec : Spek(
{
describe("blah blah") {
given("blah blah") {
var fileContent: String = ""
beforeEachTest {
// How to read the file.html in src/test/resources/html/
fileContent = ...
}
it("should blah blah") {
...
}
}
}
}
)
val fileContent = MySpec::class.java.getResource("/html/file.html").readText()
不知道为什么这这么难,但我发现的最简单的方法(无需参考特定类)是:
fun getResourceAsText(path: String): String? =
object {}.javaClass.getResource(path)?.readText()
如果没有找到具有此名称的资源(
如文档),它返回
null
。
然后传入绝对URL,例如
val html = getResourceAsText("/www/index.html")!!
另一个略有不同的解决方案:
@Test
fun basicTest() {
"/html/file.html".asResource {
// test on `it` here...
println(it)
}
}
fun String.asResource(work: (String) -> Unit) {
val content = this.javaClass::class.java.getResource(this).readText()
work(content)
}
略有不同的解决方案:
class MySpec : Spek({
describe("blah blah") {
given("blah blah") {
var fileContent = ""
beforeEachTest {
html = this.javaClass.getResource("/html/file.html").readText()
}
it("should blah blah") {
...
}
}
}
})
Kotlin + 弹簧方式:
@Autowired
private lateinit var resourceLoader: ResourceLoader
fun load() {
val html = resourceLoader.getResource("classpath:html/file.html").file
.readText(charset = Charsets.UTF_8)
}
使用谷歌Guava库资源类:
import com.google.common.io.Resources;
val fileContent: String = Resources.getResource("/html/file.html").readText()
private fun loadResource(file: String) = {}::class.java.getResource(file).readText()
val fileContent = javaClass.getResource("/html/file.html").readText()
这是我喜欢的方式:
fun getResourceText(path: String): String {
return File(ClassLoader.getSystemResource(path).file).readText()
}
这个顶级 kotlin 函数将在任何情况下完成这项工作
fun loadResource(path: String): URL {
return Thread.currentThread().contextClassLoader.getResource(path)
}
或者如果你想要更强大的功能
fun loadResource(path: String): URL {
val resource = Thread.currentThread().contextClassLoader.getResource(path)
requireNotNull(resource) { "Resource $path not found" }
return resource
}
仅供参考:在上述所有情况下。
getResource()
是使用 nullable 的不安全方式。
没有在本地尝试过,但我更喜欢这种方式:
fun readFile(resourcePath: String) = String::class.java.getResource(resourcePath)?.readText() ?: "<handle default. or handle custom exception>"
甚至作为自定义数据类型函数
private fun String.asResource() = this::class.java.getResource(resourcePath)?.readText() ?: "<handle default. or handle custom exception>"
然后你可以直接在路径上调用:
// For suppose
val path = "/src/test/resources"
val content = path.asResource()
我更喜欢这样的阅读资源:
object {}.javaClass.getResourceAsStream("/html/file.html")?.use { it.reader(Charsets.UTF_8).readText() }
getResourceAsStream
代替getResource
。类路径上的资源基本上可以在任何地方。例如打包在另一个 .jar 文件中。getResource
方法返回的 URL 类访问资源将失败。但是通过方法getResourceAsStream
访问在任何情况下都有效。object {}
-这不是很好的语法,但它不依赖于您的类的名称MyClass
,甚至可以在静态(补偿对象)块中工作。use
关闭流 - 在大多数情况下没有必要,但可能有一些特殊的类加载器,可能需要它。reader(Charsets.UTF_8)
- UTF_8 是默认编码,但我更喜欢明确。如果您将以其他编码方式对您的资源文件进行编码,例如ISO-8859-2
你不会忽视它。另一种处理空资源的变体:
val content = object {}.javaClass
.getResource("/html/file.html")
?.let(URL::readText)
?: error("Cannot open/find the file")
// ?: "default text" // Instead of error()
fun Any.resourceString(path: String): String =
this.javaClass.getResource(path)?.readText() ?: error("Can't load resource at $path")
对该扩展函数的调用看起来相对于进行调用的类。
您可能会发现 File 类很有用:
import java.io.File
fun main(args: Array<String>) {
val content = File("src/main/resources/input.txt").readText()
print(content)
}