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

问题描述 投票:0回答:3

想象一下我具有以下类结构:

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

我正在对Child.method进行Spock测试,并想验证是否从Parent.method中调用了Child.method。我做了一些研究,但还没有找到令人满意的解决方案来解决我的问题。

如何在Spock测试中验证在Child.method的调用中还调用了超类方法(Parent.method)?

已知的解决方案:在Child中,将super.method()移至单独的程序包专用方法。

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

java unit-testing groovy spock
3个回答
0
投票

tim_yates评论:

您为什么要对此进行测试?您不知道是在执行超类计算吗?

我完全同意。我不会进行测试,因为正如@Override所暗示的那样,合同是一个替代,委托给超类方法是可选的。为什么要强迫用户调用超类方法?但是正如Tim所说,您可以测试对您很重要的副作用。这是一个小例子,一个副作用是字段分配,另一个副作用是写入System.out的内容(可能很愚蠢,但只是为了显示模拟中不明显的内容):

package de.scrum_master.stackoverflow.q60167623; public class Parent { protected String name; public void method() { // Some calculations System.out.println("parent method"); name = "John Doe"; } }

package de.scrum_master.stackoverflow.q60167623;

class Child extends Parent {
  @Override
  public void method() {
    super.method();
    // Some additional logic
    System.out.println("child method");
  }

  public static void main(String[] args) {
    new Child().method();
  }
}
package de.scrum_master.stackoverflow.q60167623

import spock.lang.Specification

class ChildTest extends Specification {
  static final PrintStream originalSysOut = System.out
  PrintStream mockSysOut = Mock()

  def setup() {
    System.out = mockSysOut
  }

  def cleanup() {
    System.out = originalSysOut
  }

  def test() {
    given:
    def child = new Child()

    when:
    child.method()

    then:
    1 * mockSysOut.println({ it.contains("parent") })
    child.name == "John Doe"
  }
}

更新:从技术上讲,您仅想做的事情是不可能的,原因是:这会破坏封装,请参见herehere,也间接地参见here。方法是overridden,这句话说明了一切。测试方法的(副作用)或结果,而不是方法的交互作用(实际上称为方法)。即使Spock手册警告某些地方规格过高,Spock的交互测试功能也被过度使用。它只会使您的测试变脆。对于诸如发布/订阅(观察者模式)之类的设计模式而言,交互测试是可以的,在这种模式下测试对象之间的交互是有意义的。


0
投票
如果需要强制执行Parent中的某些功能,则应通过设计而不是测试来强制执行。

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 } }

您当然不能将其设为abstract,而只是为additionalLogic()添加一个无操作实现。

-1
投票
我从未使用过Spock框架,但我认为您可以使用运算符或反射的实例来检查Parent.method中实例的类型。
© www.soinside.com 2019 - 2024. All rights reserved.