类参数化测试

huangapple go评论78阅读模式
英文:

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&lt;A, B&gt; {}

<!-- language: java -->

package de.scrum_master.stackoverflow.q61032514;

import java.time.LocalDate;

public class DueDateEditor extends TreeTableCell&lt;TaskItem, LocalDate&gt; {
  String text;

  public boolean isEmpty() {
    return text == null || text.trim() == &quot;&quot;;
  }

  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 &quot;test generic type arguments for DueDateEditor&quot;() {
    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 &#39;actualTypeArguments&#39; 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&lt;String, LocalDate&gt;, it fails like this:

genericSuperclass.actualTypeArguments == [TaskItem, LocalDate]
|                 |                   |   |         |
|                 |                   |   |         class java.time.LocalDate
|                 |                   |   class de.scrum_master.stackoverflow.q61032514.TaskItem
|                 |                   false
|                 [&lt;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]&gt;, &lt;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]&gt;]
de.scrum_master.stackoverflow.q61032514.TreeTableCell&lt;java.lang.String, java.time.LocalDate&gt;

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 &#39;actualTypeArguments&#39; 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]
|                 [&lt;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]&gt;, &lt;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]&gt;]
de.scrum_master.stackoverflow.q61032514.TreeTableCell&lt;java.lang.String, java.time.LocalDate&gt;

huangapple
  • 本文由 发表于 2020年4月5日 00:46:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/61031440.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定