Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何验证是否在Spock中调用了超类方法?_Java_Unit Testing_Groovy_Spock - Fatal编程技术网

Java 如何验证是否在Spock中调用了超类方法?

Java 如何验证是否在Spock中调用了超类方法?,java,unit-testing,groovy,spock,Java,Unit Testing,Groovy,Spock,假设我的班级结构如下: 类父类{ 公开作废法(){ //一些计算 } } 类子级扩展父级{ @凌驾 公开作废法(){ super.method(); //一些附加逻辑 } } 我正在测试子.method,想验证是否从子.method调用了父.method。我做了一些研究,但没有找到任何令人满意的解决方案 如何在Spock测试中验证调用Child.method时是否也调用了超类方法(Parent.method) 已知解决方案:在Child中,将super.method()移动到单独的包私有方法

假设我的班级结构如下:

类父类{
公开作废法(){
//一些计算
}
}
类子级扩展父级{
@凌驾
公开作废法(){
super.method();
//一些附加逻辑
}
}
我正在测试
子.method
,想验证是否从
子.method
调用了
父.method
。我做了一些研究,但没有找到任何令人满意的解决方案

如何在Spock测试中验证调用
Child.method
时是否也调用了超类方法(
Parent.method

已知解决方案:在
Child
中,将
super.method()
移动到单独的包私有方法


我想知道是否有更好的解决方案。

我从未使用过Spock框架,但我认为您可以使用操作符或反射实例检查Parent.method中的实例类型。

tim_yates评论道:


你为什么要测试这个?你不能告诉我超级类的计算是怎么进行的吗

我完全同意。我不会对此进行测试,因为正如
@Override
所暗示的那样,契约是一种重写,对超类方法的委托是可选的。为什么要强迫用户调用超级类方法?但正如蒂姆所说,你可以测试对你来说很重要的副作用。下面是一个小例子,一个副作用是字段分配,另一个副作用是写入
System.out
(可能很傻,但只是为了用模拟显示一些不明显的东西):

package de.scrum_master.stackoverflow.q60167623;
公共类父类{
受保护的字符串名称;
公开作废法(){
//一些计算
System.out.println(“父方法”);
name=“约翰·多伊”;
}
}
package de.scrum_master.stackoverflow.q60167623;
类子级扩展父级{
@凌驾
公开作废法(){
super.method();
//一些附加逻辑
System.out.println(“子方法”);
}
公共静态void main(字符串[]args){
new Child().method();
}
}
package de.scrum_master.stackoverflow.q60167623
导入spock.lang.Specification
类ChildTest扩展了规范{
静态最终打印流originalSysOut=System.out
PrintStream mockSysOut=Mock()
def设置(){
System.out=mockSysOut
}
def cleanup(){
System.out=原始SysOut
}
def测试(){
鉴于:
def child=new child()
什么时候:
child.method()
然后:
1*mockSysOut.println({it.contains(“父”)})
child.name==“John Doe”
}
}

更新:您想要做的事情在技术上是不可能的,原因是:它会破坏封装,请参阅。这个方法被覆盖了,这个词说明了一切。测试方法的(副作用)或结果,而不是其交互作用(实际调用)。Spock的交互测试功能被过度使用,即使Spock手册警告某些地方存在过度规范。这只会让你的测试变得脆弱。交互测试对于诸如发布/订阅(观察者模式)之类的设计模式来说是可以的,在这种模式下,测试对象之间的交互是有意义的。

如果需要强制调用父级
中的某些功能,则应通过设计而不是测试来强制执行

abstract class Parent {
  public final void method() {
    // Some calculations
    additionalLogic();
  }

  protected abstract void additionalLogic();
}

class Child extends Parent {
  @Override
  protected void additionalLogic() {
    super.method();
    // Some additional logic
  }
}

当然,您不能将其抽象化,而只是为
additionalLogic()
添加一个不可操作的实现。

tim_yates和kriegaex是丛林中的大野兽,当涉及到好的和坏的Spock,或者通常是TDD风格的测试时。。。他们不止一次(正确地)以他们在这里所做的方式来区分我的问题,基本上是基于测试代码而不是实现

不过有时候很难。可能在某些情况下,您需要测试调用
super.doSomething()
。我正在使用TDD组装一个
TreeTableView
的编辑器,它已经完成了一个“spike”,我在没有测试的情况下就冲到了前面。可以看到“尖峰”。在对我的回答的建设性评论中,kleopatra建议我检查(即在应用程序代码中加入
if
),以确保
super.startEdit()
确实在继续之前开始编辑单元格,因此在这种情况下,仅测试
super.startEdit()的“副作用”是不够的
由于
isEditing()
现在返回
true
。你真的需要知道你的类的
startEdit()
实际上只做了调用
super.startEdit()

然而,我不相信这是可以做到的,蒂姆·耶茨或克里加克斯几乎肯定会说,如果可能的话,你是如何做到的

因此,我建议的TDD解决方案如下:

def 'super start edit should be called if cell is not empty'(){
    given:
    // NB has to be GroovySpy because isEmpty() is final
    DueDateEditor editor = GroovySpy( DueDateEditor ){
        isEmpty() >> false
    }

    when:
    editor.startEdit()

    then:
    1 * editor.callSuperStartEdit()
}


class DueDateEditor extends TreeTableCell {

    @Override
    void startEdit(){
        if( ! isEmpty() ) {
            // this is the line you have to add to make the test pass
            callSuperStartEdit()
        }
    }

    def callSuperStartEdit(){
        super.startEdit()
    }
}
我认为你必须“繁殖”一种人工的单一用途的方法,因为准确地说,根本没有副作用


实际上,我将参数化这个测试,以便它在第二次调用中返回
true
isEmpty()
,并要求在这种情况下不调用该方法

你为什么要测试这个?你不能告诉我超级类计算是在什么时候执行的吗?因为我的代码可能会在之后更新/更改,我必须确保通过实现测试调用此方法。我假设它会有副作用?你不能测试一下这个效果吗?这个答案正好是设计模式。