【发布时间】:2018-12-22 02:03:35
【问题描述】:
我的场景:
我正在构建一个使用 Kotlin 和 SpringBoot 2.0.3 的应用程序。我正在尝试在 JUnit5 中编写所有单元测试。这三个对我来说都是新的,所以我有点挣扎。
我正在使用 @ConfigurationProperties 类(而不是 @Value)将值从我的 application.yml 注入到我的 Spring 上下文中。
@Configuration
@ConfigurationProperties(prefix = "amazon.aws.s3")
class AmazonS3Config {
val s3Enabled: Boolean = false
val region: String = ""
val accessKeyId: String = ""
val secretAccessKey: String = ""
val bucketName: String = ""
}
然后我有一个利用这些属性的 Kotlin 类,遵循 Kotlin/Spring 最佳实践将注入的类定义为构造函数参数。
class VqsS3FileReader(val amazonS3Config: AmazonS3Config) : VqsFileReader {
companion object: mu.KLogging()
override fun getInputStream(filePath: String): InputStream {
val region: String = amazonS3Config.region
val accessKeyId: String = amazonS3Config.accessKeyId
val secretAccessKey: String = amazonS3Config.secretAccessKey
val bucketName: String = amazonS3Config.bucketName
logger.debug { "The configured s3Enabled is: $s3Enabled" }
logger.debug { "The configured region is: $region" }
logger.debug { "The configured accessKeyId is: $accessKeyId" }
logger.debug { "The configured secretAccessKey is: $secretAccessKey" }
logger.debug { "The configured bucketName is: $bucketName" }
val file: File? = File(filePath)
//This method is not yet implemented, just read a file from local disk for now
return file?.inputStream() ?: throw FileNotFoundException("File at $filePath is null")
}
}
我还没有完成这个实现,因为我正试图让单元测试首先工作。所以目前,这个方法实际上并没有到达 S3,只是流式传输一个本地文件。
我的单元测试是我卡住的地方。我不知道如何将 application.yml 中的属性注入测试上下文。由于 ConfigProperty 类是作为构造参数传递的,所以我在单元测试中建立服务时必须传递它。我尝试了各种不起作用的解决方案。我发现这条信息很有帮助:
如果正在使用 Spring Boot,则可以使用 @ConfigurationProperties 而不是 @Value 注释,但目前这仅适用于 lateinit 或可为空的 var 属性(建议使用前者),因为尚不支持由构造函数初始化的不可变类。
所以这意味着我不能使用 class VqsS3FileReaderTest(amazonS3Config: AmazonS3Config): TestBase() { ... } 然后将配置传递给我的服务。
这是我目前拥有的:
@ActiveProfiles("test")
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@ExtendWith(SpringExtension::class)
@ContextConfiguration(classes = [AmazonS3Config::class, VqsS3FileReader::class])
class VqsS3FileReaderTest(): TestBase() {
@Autowired
private lateinit var amazonS3Config: AmazonS3Config
@Autowired
private lateinit var fileReader: VqsS3FileReader
val filePath: String = "/fileio/sampleLocalFile.txt"
@Test
fun `can get input stream from a valid file path` () {
fileReader = VqsS3FileReader(amazonS3Config)
val sampleLocalFile: File? = getFile(filePath) //getFile is defined in the TestBase class, it just gets a file in my "resources" dir
if (sampleLocalFile != null) {
val inStream: InputStream = fileReader.getInputStream(sampleLocalFile.absolutePath)
val content: String = inStream.readBytes().toString(Charset.defaultCharset())
assert.that(content, startsWith("Lorem Ipsum"))
} else {
fail { "The file at $filePath was not found." }
}
}
}
有了这个,我的测试运行,我的上下文似乎设置正确,但我的 application.yml 的属性没有被注入。对于我的调试输出,我看到以下内容:
08:46:43.111 [main] DEBUG com.ilmn.vqs.fileio.VqsS3FileReader - The configured s3Enabled is: false
08:46:43.111 [main] DEBUG com.ilmn.vqs.fileio.VqsS3FileReader - The configured region is:
08:46:43.112 [main] DEBUG com.ilmn.vqs.fileio.VqsS3FileReader - The configured accessKeyId is:
08:46:43.112 [main] DEBUG com.ilmn.vqs.fileio.VqsS3FileReader - The configured secretAccessKey is:
08:46:43.112 [main] DEBUG com.ilmn.vqs.fileio.VqsS3FileReader - The configured bucketName is:
所有空字符串,这是默认值。不是我在 application.yml 中的值:
amazon.aws.s3:
s3Enabled: true
region: us-west-2
accessKeyId: unknown-at-this-time
secretAccessKey: unknown-at-this-time
bucketName: test-bucket
【问题讨论】:
标签: spring unit-testing spring-boot kotlin junit5