5

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(我很难相信永远不会有用于)

4

3 回答 3

5

使用模拟间谍。您可以使用该测试框架检查几乎所有方法调用。

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

于 2012-12-07T11:17:19.347 回答
2

这可能不是您想要的答案(即不是一种解决方法),而是您应得的答案,但您永远不应该重写方法并调用 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测试中必须mock超类方法调用,代码封闭修改开放扩展,即更易维护.

于 2014-04-09T17:37:18.397 回答
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
    }
  };

 }
于 2012-12-07T11:34:48.747 回答