英文:
Test for parameterisation of a class
问题
以下是翻译好的部分:
在我的测试中,我有以下代码:
假设:
def dueDateCol = App.instance.fxmlController.treeTableView.columns.get(1)
当:
def editorCell = dueDateCol.cellFactory.call(dueDateCol)
那么:
editorCell instanceof TreeTableCell<TaskItem, LocalDate>
我的应用程序代码目前是这样的:
class DueDateEditor extends TreeTableCell {
}
... 但是测试通过了!我希望在应用程序代码正确地参数化之前,测试会失败:
class DueDateEditor extends TreeTableCell<TaskItem, LocalDate> {
}
英文:
In my test I have this:
given:
def dueDateCol = App.instance.fxmlController.treeTableView.columns.get( 1 )
when:
def editorCell = dueDateCol.cellFactory.call( dueDateCol )
then:
editorCell instanceof TreeTableCell<TaskItem, LocalDate>
My app code is currently this:
class DueDateEditor extends TreeTableCell {
}
... but the test passes! I want it to fail until the app code is correctly parameterised:
class DueDateEditor extends TreeTableCell<TaskItem, LocalDate>{
}
答案1
得分: 1
请确认以下翻译内容:
就像在我的其他回答中一样,一个一般性的观点:为什么要测试这样的东西呢?如果你要测试的话,我更倾向于确保在编译(或后编译)过程中以某种方式整合静态类型检查。理想情况下,编译器应该在违反类似于这样的合约时抛出错误。
不管怎样,对于这个问题,你可以这样做(应用程序和测试类都是我在其他回答中的MCVE的逻辑延续):
package de.scrum_master.stackoverflow.q61032514;
public class TaskItem {}
package de.scrum_master.stackoverflow.q61032514;
public class TreeTableCell<A, B> {}
package de.scrum_master.stackoverflow.q61032514;
import java.time.LocalDate;
public class DueDateEditor extends TreeTableCell<TaskItem, LocalDate> {
String text;
public boolean isEmpty() {
return text == null || text.trim() == "";
}
public void startEdit() {
if (!isEmpty())
callSuperStartEdit();
}
public void callSuperStartEdit() {}
}
现在以下测试通过:
package de.scrum_master.stackoverflow.q61032514
import spock.lang.Specification
import java.lang.reflect.ParameterizedType
import java.time.LocalDate
class DueDateEditorTest extends Specification {
def "test generic type arguments for DueDateEditor"() {
given:
def superclass = DueDateEditor.superclass
def genericSuperclass = DueDateEditor.genericSuperclass
expect:
superclass == TreeTableCell
genericSuperclass instanceof ParameterizedType
genericSuperclass.actualTypeArguments == [TaskItem, LocalDate]
// 或者,如果你想避免在IDE中出现下划线的'actualTypeArguments':
// (genericSuperclass as ParameterizedType).actualTypeArguments == [TaskItem, LocalDate]
}
}
如果你将被测试的类更改为DueDateEditor extends TreeTableCell
,测试会失败,错误消息如下:
条件不满足:
genericSuperclass instanceof ParameterizedType
| | |
| false interface java.lang.reflect.ParameterizedType
class de.scrum_master.stackoverflow.q61032514.TreeTableCell (java.lang.Class)
如果你更改为类似于DueDateEditor extends TreeTableCell<String, LocalDate>
的内容,测试会像这样失败:
genericSuperclass.actualTypeArguments == [TaskItem, LocalDate]
| | | | |
| | | | class java.time.LocalDate
| | | class de.scrum_master.stackoverflow.q61032514.TaskItem
| | false
| [<java.lang.Class@192d43ce cachedConstructor=null newInstanceCallerCache=null name=java.lang.String reflectionData=java.lang.ref.SoftReference@54709809 classRedefinedCount=0 genericInfo=sun.reflect.generics.repository.ClassRepository@2a2da905 enumConstants=null enumConstantDirectory=null annotationData=java.lang.Class$AnnotationData@24f360b2 annotationType=null classValueMap=[java.lang.ClassValue$Identity@39c0f4a:java.lang.ClassValue$Entry@60cf80e7]>, <java.lang.Class@38e79ae3 cachedConstructor=null newInstanceCallerCache=null name=java.time.LocalDate reflectionData=java.lang.ref.SoftReference@302fec27 classRedefinedCount=0 genericInfo=sun.reflect.generics.repository.ClassRepository@770d0ea6 enumConstants=null enumConstantDirectory=null annotationData=null annotationType=null classValueMap=[java.lang.ClassValue$Identity@39c0f4a:java.lang.ClassValue$Entry@48c40605]>]
de.scrum_master.stackoverflow.q61032514.TreeTableCell<java.lang.String, java.time.LocalDate>
或者如果你想在错误消息中更好地比较列表,你可以使用toList()
,像这样:
genericSuperclass.actualTypeArguments.toList() == [TaskItem, LocalDate]
// 或者,如果你想避免在IDE中出现下划线的'actualTypeArguments':
//(genericSuperclass as ParameterizedType).actualTypeArguments.toList() == [TaskItem, LocalDate]
然后最后的错误消息会变成:
条件不满足:
genericSuperclass.actualTypeArguments.toList() == [TaskItem, LocalDate]
| | | | | |
| | | | | class java.time.LocalDate
| | | | class de.scrum_master.stackoverflow.q61032514.TaskItem
| | | false
| | [class java.lang.String, class java.time.LocalDate]
| [<java.lang.Class@192d43ce cachedConstructor=null newInstanceCallerCache=null name=java.lang.String reflectionData=java.lang.ref.SoftReference@60cf80e7 classRedefinedCount=0 genericInfo=sun.reflect.generics.repository.ClassRepository@302fec27 enumConstants=null enumConstantDirectory=null annotationData=java.lang.Class$AnnotationData@770d0ea6 annotationType=null classValueMap=[java.lang.ClassValue$Identity@39c0f4a:java.lang.ClassValue$Entry@48c40605]>, <java.lang.Class@2d2ffcb7 cachedConstructor=null newInstanceCallerCache=null name=java.time.LocalDate reflectionData=java.lang.ref.SoftReference@54107f42 classRedefinedCount=0 genericInfo=sun.reflect.generics.repository.ClassRepository@1b11ef33 enumConstants=null enumConstantDirectory=null annotationData=null annotationType=null classValueMap=[java.lang.ClassValue$Identity@39c0f4a:java.lang.ClassValue$Entry@476aac9]>]
de.scrum_master.stackoverflow.q61032514.TreeTableCell<java.lang.String, java.time.LocalDate>
英文:
Again, like in my other answer, a general remark: Why would you test such a thing? And if you test it, I would rather make sure to somehow integrate static type checks into the compilation (or post-compilation) process. Ideally, the compiler should throw an error if a contract like this is violated.
Anyway, for what it is worth, you could do this (both application and test classes are logical continuations of my MCVE in the other answer):
<!-- language: java -->
package de.scrum_master.stackoverflow.q61032514;
public class TaskItem {}
<!-- language: java -->
package de.scrum_master.stackoverflow.q61032514;
public class TreeTableCell<A, B> {}
<!-- language: java -->
package de.scrum_master.stackoverflow.q61032514;
import java.time.LocalDate;
public class DueDateEditor extends TreeTableCell<TaskItem, LocalDate> {
String text;
public boolean isEmpty() {
return text == null || text.trim() == "";
}
public void startEdit() {
if (!isEmpty())
callSuperStartEdit();
}
public void callSuperStartEdit() {}
}
Now the following test passes:
<!-- language: lang-groovy -->
package de.scrum_master.stackoverflow.q61032514
import spock.lang.Specification
import java.lang.reflect.ParameterizedType
import java.time.LocalDate
class DueDateEditorTest extends Specification {
def "test generic type arguments for DueDateEditor"() {
given:
def superclass = DueDateEditor.superclass
def genericSuperclass = DueDateEditor.genericSuperclass
expect:
superclass == TreeTableCell
genericSuperclass instanceof ParameterizedType
genericSuperclass.actualTypeArguments == [TaskItem, LocalDate]
// Or, if you want to avoid the underlined 'actualTypeArguments' in your IDE:
// (genericSuperclass as ParameterizedType).actualTypeArguments == [TaskItem, LocalDate]
}
}
If you change the class under test to DueDateEditor extends TreeTableCell
, the test fails like this:
Condition not satisfied:
genericSuperclass instanceof ParameterizedType
| | |
| false interface java.lang.reflect.ParameterizedType
class de.scrum_master.stackoverflow.q61032514.TreeTableCell (java.lang.Class)
If you change to something like DueDateEditor extends TreeTableCell<String, LocalDate>
, it fails like this:
genericSuperclass.actualTypeArguments == [TaskItem, LocalDate]
| | | | |
| | | | class java.time.LocalDate
| | | class de.scrum_master.stackoverflow.q61032514.TaskItem
| | false
| [<java.lang.Class@192d43ce cachedConstructor=null newInstanceCallerCache=null name=java.lang.String reflectionData=java.lang.ref.SoftReference@54709809 classRedefinedCount=0 genericInfo=sun.reflect.generics.repository.ClassRepository@2a2da905 enumConstants=null enumConstantDirectory=null annotationData=java.lang.Class$AnnotationData@24f360b2 annotationType=null classValueMap=[java.lang.ClassValue$Identity@39c0f4a:java.lang.ClassValue$Entry@60cf80e7]>, <java.lang.Class@38e79ae3 cachedConstructor=null newInstanceCallerCache=null name=java.time.LocalDate reflectionData=java.lang.ref.SoftReference@302fec27 classRedefinedCount=0 genericInfo=sun.reflect.generics.repository.ClassRepository@770d0ea6 enumConstants=null enumConstantDirectory=null annotationData=null annotationType=null classValueMap=[java.lang.ClassValue$Identity@39c0f4a:java.lang.ClassValue$Entry@48c40605]>]
de.scrum_master.stackoverflow.q61032514.TreeTableCell<java.lang.String, java.time.LocalDate>
Or if you want to better compare lists in the error message, you could use toList()
like this:
<!-- language: lang-groovy -->
genericSuperclass.actualTypeArguments.toList() == [TaskItem, LocalDate]
// Or, if you want to avoid the underlined 'actualTypeArguments' in your IDE:
//(genericSuperclass as ParameterizedType).actualTypeArguments.toList() == [TaskItem, LocalDate]
Then the last error message would change to:
Condition not satisfied:
genericSuperclass.actualTypeArguments.toList() == [TaskItem, LocalDate]
| | | | | |
| | | | | class java.time.LocalDate
| | | | class de.scrum_master.stackoverflow.q61032514.TaskItem
| | | false
| | [class java.lang.String, class java.time.LocalDate]
| [<java.lang.Class@192d43ce cachedConstructor=null newInstanceCallerCache=null name=java.lang.String reflectionData=java.lang.ref.SoftReference@60cf80e7 classRedefinedCount=0 genericInfo=sun.reflect.generics.repository.ClassRepository@302fec27 enumConstants=null enumConstantDirectory=null annotationData=java.lang.Class$AnnotationData@770d0ea6 annotationType=null classValueMap=[java.lang.ClassValue$Identity@39c0f4a:java.lang.ClassValue$Entry@48c40605]>, <java.lang.Class@2d2ffcb7 cachedConstructor=null newInstanceCallerCache=null name=java.time.LocalDate reflectionData=java.lang.ref.SoftReference@54107f42 classRedefinedCount=0 genericInfo=sun.reflect.generics.repository.ClassRepository@1b11ef33 enumConstants=null enumConstantDirectory=null annotationData=null annotationType=null classValueMap=[java.lang.ClassValue$Identity@39c0f4a:java.lang.ClassValue$Entry@476aac9]>]
de.scrum_master.stackoverflow.q61032514.TreeTableCell<java.lang.String, java.time.LocalDate>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论