如何对超级调用的重写方法进行单元测试?

时间:2012-12-07 11:10:45

标签: java unit-testing junit

http://stackoverflow.com/questions/6645263/unit-testing-overridden-methods-which-call-super(这个问题有类似的措辞,但不一样)

我有以下几点:

public class SuperClass {
   private int superClassInteger = 2;

   public void superClassMethod() {
      superClassInteger = 5;
   }

   public int getSuperClassInteger() {
      return superClassInteger();
   }
}

然后在我的测试中我有:

public class SuperClassTest {
   public void testSuperClassMethod() {
       SuperClass superClass = new SuperClass();
       superClass.superClassMethod();
       assertEquals(5, super.getSuperClassInteger())
   }
}

然后我有一个子类:

public class SubClass {
   private int subClassInteger = 2;

   public void subClassMethod() {
      super.superClassMethod();
      subClassInteger = 32;
   }

   public int getSuperClassInteger() {
      subClassInteger;
   }
}

然后我测试子类:

public class SubClassTest {
   public void testSubClassMethod() {
       SubClass subClass = new SubClass();
       subClass.subClassMethod();
       assertEquals(5, subclass.getSuperClassInteger());
       assertEquals(32, subclass.getSubClassInteger())
   }
}

我的问题是,为了测试子类的行为,我正在重复我对超类的测试代码。我可以拿出:assertEquals(5, subclass.getSuperClassInteger());因为我只想测试子类的业务逻辑。但是,问题在于如果有人意外删除了对superClassMethod的调用,测试仍会通过。所以我需要验证对super的调用。测试这个用例的常用方法是什么?

注意:我知道组合/策略模式与继承有助于解决这个问题但是为了解决这个问题你基本上说我不应该覆盖一个方法并在我的代码中调用super(我很难相信会有从来没有用过)

3 个答案:

答案 0 :(得分:5)

使用mockito间谍。您可以使用该测试框架检查几乎任何方法调用。

http://code.google.com/p/mockito/

答案 1 :(得分:3)

这可能不是你想要的答案(即不是解决方法),但你得到的答案但是你永远不应该覆盖方法并调用super。

我正在开展一项遗产项目,这项目很多,维护,调试和测试都是一场噩梦。

相反,使用带有模板方法模式的抽象类更好:

之前

public class SuperClass<T> {
  public void include(T t) {
    validate(T);
    dao.save(T);
  }

  // I've found code like that.
  public void validate(T t) {
  }
}

public class SubClass1 extends SuperClass<MyClass> {
  @Override
  public void include(MyClass mc) {
    doStuff(mc);
    doMoreStuff(mc);
    super.include(mc);
  }

  @Override
  public void validate(MyClass mc) {
    doValidationStuff();
  }
}

public class SubClass2 extends SuperClass<AnotherClass> {
  @Override
  public void include(AnotherClass ac) {
    doDifferentStuff();
    super.include(mc);
  }
}

之后

public abstract class AbstractClass<T> {
  abstract void validate(T t);

  // this method can now be tested
  public void include(T t) {
    validate(T);
    dao.save(T);
  }
}

public class Class1 extends AbstractClass<MyClass> {
  public void validate(MyClass mc) {
    doValidationStuff();
    doStuff(mc);
    doMoreStuff(mc);
  }
}

public class Class2 extends AbstractClass<AnotherClass> {
  public void validate(AnotherClass ac) {
    doDifferentStuff();
  }
}

正如您所看到的,这种重构简化了维护和测试,您不必担心必须在Class1和Class2测试中模拟超类方法调用,并且代码关闭以进行修改并打开扩展,即更易于维护。

答案 2 :(得分:1)

使用JMockit并通过验证检查对super的调用。

JMockit

此示例

public void test {
  SubClass subClass = new SubClass();
  subClass.subClassMethod();
  new Verifications() {
    // mock only this method of superClass - and only in this test
    @Mocked (methods = "superClassMethod") 
    SuperClass superClass; 
    {
     superClass.superClassMethod();
     times = 1; // specify invocation count
    }
  };

 }