我们正在使用反射使我们的测试能够在不同的环境中开始。
典型的测试如下:
class TestClass {
val environment: Environment = generateEnvironment("jUnit")
val path: String = environment.path
//Do test stuff
}
我们正在使用这样的反射:
class PostgresqlTest{
val classList: List<KClass<*>> = listOf(TestClass::class)
val postgresEnv = generateEnvironment("postgres")
@TestFactory
fun generateTests(): List<DynamicTest> = classList.flatMap { testClass ->
val instance = testClass.createInstance()
environmentProperty(testclass).setter.call(instance, postgresEnv)
//<<generate the dynamic tests>>
}
fun environmentProperty(testClass: KClass<*>) =
testClass.memberProperties.find {
it.returnType.classifier == Environment::class
} as KMutableProperty<*>
}
现在我们在PostgresqlTest中遇到了path != environment.path
我知道可以使用类似lazy或get()的方法在TestClass中解决此问题
class TestClass {
val environment: Environment = generateEnvironment("jUnit")
val path: String by lazy { environment.path }
// OR
val path: String get() = environment.path
}
但是,这似乎对将来的开发人员来说是一个潜在的陷阱,特别是因为第一个代码段将在TestClass中工作,并且仅在环境被覆盖的测试中失败。
在覆盖属性时确保path == environment.path
最干净的方法是什么?
答案 0 :(得分:0)
理想情况下,如果您使用的是依赖项注入框架(例如Dagger),则希望测试类仅注入Environment
(这将仅在提供环境路径之后才引用它),例如:
class TestClass {
@Inject lateinit var environment: Environment
private lateinit var path: String
@Before fun setup() {
// do injection here
path = environment.path
}
}
否则,我认为接口委托在这里可能是一个不错的选择,并且完全避免了反思。例如,创建一个显示EnvironmentHost
和environment
属性的path
:
interface EnvironmentHost {
var environment: Environment
val path: String
}
在此处为测试类创建一个实现:
class TestEnvironmentHost : EnvironmentHost {
override var environment: Environment = generateEnvironment("jUnit")
override val path: String
get() = environment.path
}
测试类现在看起来像:
class TestClass : EnvironmentHost by TestEnvironmentHost() {
@Test fun myTest() {
val myPath = path
val myEnvironment = environment
}
}
您的测试工厂可以简化为:
@TestFactory
fun generateTests(): List<DynamicTests> = classList.flatMap { testClass ->
val instance = testClass.createInstance()
// Assign an environment if the test is an EnvironmentHost. If not,
// you could choose to treat that as a failure and require the test
// class to be an EnvironmentHost.
(instance as? EnvironmentHost)?.environment = postgresEnv
...
}
答案 1 :(得分:0)
我最终为每种环境在gradle中创建了一个新的测试任务:
task postgresqlIntegrationTest(type: Test, group: "Verification", description: "Runs integration tests on postgresql.") {
dependsOn compileTestKotlin
mustRunAfter test
environment "env", "postgresql"
useJUnitPlatform {
filter {
includeTestsMatching "*IT"
}
}
}
我的测试类仅在其中加载环境,如下所示:
class TestClass {
val environment: Environment = generateEnvironment(System.getenv("env") ?: "junit")
//Do test stuff
}