在 类 中测试扩展函数
Testing extension functions inside classes
如果我们想在一个类型上测试一个扩展函数,我们可以创建一个这个类型的实例,调用函数并检查返回值。但是如何测试 类 中定义的扩展函数呢?
abstract class AbstractClass<T> {
fun doStuff(): T = "Hello".foo()
abstract fun String.foo(): T
}
class SubClass1: AbstractClass<Int>() {
override fun String.foo(): Int = 1
}
class SubClass2: AbstractClass<Boolean>() {
override fun String.foo(): Boolean = true
}
我们如何测试类SubClass1
和SubClass2
中方法foo()
的逻辑?有可能吗?
我知道我可以更改设计来测试它。我想到了两种可能性:
不要使用扩展函数。 ¯\_(ツ)_/¯
abstract class AbstractClass<T> {
fun doStuff(): T = foo("Hello")
abstract fun foo(string: String): T
}
class SubClass1: AbstractClass<Int>() {
override fun foo(string: String): Int = 1
}
然后我们可以创建一个对象SubClass1
,调用foo()
并检查返回值。
创建具有 internal
可见性的附加扩展函数只是为了测试逻辑。
class SubClass1: AbstractClass<Int>() {
override fun String.foo(): Int = internalFoo()
}
internal fun String.internalFoo(): Int = 1
然后我们可以创建一个对象String
,调用internalFoo()
并检查返回值。但是,我不喜欢这个解决方案,因为我们可以更改 override fun String.foo(): Int
的主体,并且我们的测试会通过。
那么,是否可以在 类 中测试扩展函数?如果没有,您将如何更改您的设计以测试他们的逻辑?
由于应该从客户的角度编写测试,我不确定它是否是有效的测试。但我确实想出了一种方法来测试它。
@Test
fun `test extension function`() {
var int = 0
SubClass1().apply {
int = "blah".foo()
}
assertThat(int, `is`(1))
}
扩展方法很棒,它们支持像 LINQ、Android KTX 中那样优美流畅的语法。
但是,扩展方法不适用于子类化。这是因为扩展本质上是 non-object-oriented。它们类似于 Java 中的静态方法,可以隐藏但不能在子类中覆盖。
如果您希望在子类中更改某些代码,请不要编写扩展方法,因为您将面临您在问题和 all of the disadvantages that static methods brings to testability 中遇到的测试障碍。
您的第一个示例绝对没有任何问题,也没有充分的理由在那里坚持使用扩展方法:
abstract class AbstractClass<T> {
fun doStuff(): T = foo("Hello")
abstract fun foo(string: String): T
}
class SubClass1: AbstractClass<Int>() {
override fun foo(string: String): Int = 1
}
如果我们想在一个类型上测试一个扩展函数,我们可以创建一个这个类型的实例,调用函数并检查返回值。但是如何测试 类 中定义的扩展函数呢?
abstract class AbstractClass<T> {
fun doStuff(): T = "Hello".foo()
abstract fun String.foo(): T
}
class SubClass1: AbstractClass<Int>() {
override fun String.foo(): Int = 1
}
class SubClass2: AbstractClass<Boolean>() {
override fun String.foo(): Boolean = true
}
我们如何测试类SubClass1
和SubClass2
中方法foo()
的逻辑?有可能吗?
我知道我可以更改设计来测试它。我想到了两种可能性:
不要使用扩展函数。 ¯\_(ツ)_/¯
abstract class AbstractClass<T> { fun doStuff(): T = foo("Hello") abstract fun foo(string: String): T } class SubClass1: AbstractClass<Int>() { override fun foo(string: String): Int = 1 }
然后我们可以创建一个对象
SubClass1
,调用foo()
并检查返回值。创建具有
internal
可见性的附加扩展函数只是为了测试逻辑。class SubClass1: AbstractClass<Int>() { override fun String.foo(): Int = internalFoo() } internal fun String.internalFoo(): Int = 1
然后我们可以创建一个对象
String
,调用internalFoo()
并检查返回值。但是,我不喜欢这个解决方案,因为我们可以更改override fun String.foo(): Int
的主体,并且我们的测试会通过。
那么,是否可以在 类 中测试扩展函数?如果没有,您将如何更改您的设计以测试他们的逻辑?
由于应该从客户的角度编写测试,我不确定它是否是有效的测试。但我确实想出了一种方法来测试它。
@Test
fun `test extension function`() {
var int = 0
SubClass1().apply {
int = "blah".foo()
}
assertThat(int, `is`(1))
}
扩展方法很棒,它们支持像 LINQ、Android KTX 中那样优美流畅的语法。
但是,扩展方法不适用于子类化。这是因为扩展本质上是 non-object-oriented。它们类似于 Java 中的静态方法,可以隐藏但不能在子类中覆盖。
如果您希望在子类中更改某些代码,请不要编写扩展方法,因为您将面临您在问题和 all of the disadvantages that static methods brings to testability 中遇到的测试障碍。
您的第一个示例绝对没有任何问题,也没有充分的理由在那里坚持使用扩展方法:
abstract class AbstractClass<T> {
fun doStuff(): T = foo("Hello")
abstract fun foo(string: String): T
}
class SubClass1: AbstractClass<Int>() {
override fun foo(string: String): Int = 1
}