使用 sub类 测试抽象 类 中的具体方法

Testing concrete methods in abstract classes using subclasses

abstract class BaseClass{

      private final Dependency dep;

      BaseClass(final Dependency dep){
             this.dep = dep;
      }
      abstract void toBeImplementedBySubclasses();

      public int concreteMethod(){
              //Do some processing
              return any_integer;
      }
}
class DerivedOne{

      @Inject
      DerivedOne(final Dependency dep){
          super(dep);
      }       

      public void toBeImplementedBySubclasses(){
           //DO SOMETHING RELEVANT TO DERIVED ONE IMPLEMENTATION
      }
}
class DerivedTwo{

      @Inject
      DerivedOne(final Dependency dep){
          super(dep);
      }   

      public void toBeImplementedBySubclasses(){
           //DO SOMETHING RELEVANT TO DERIVED TWO IMPLEMENTATION
      }
}

我想测试抽象的具体方法class。 如果我在单元测试中测试基础 class 中的具体方法是否可以用于两个派生的 classes 中的任何一个,或者还有其他方法吗?

因此,如果为 DerivedOne class 编写测试,它将包括对所有方法的测试以及基础 class 的具体方法。 我知道有一个东西 "Mockito.CALLS_REAL_METHODS",我们可以使用它来测试抽象 classes,但在我的例子中,我的基础 class 有一些依赖关系,我 initalise/inject 使用 super()我派生的 classes 的内部构造函数,所以我不能使用 CALLS_REALS_METHODS

这里有两种选择。

首先,你可以写一个抽象的 test class,它处理测试这些方法,然后你的具体实现的测试 classes其余的部分。例如:

public abstract class YourAbstractClassTest {

    protected abstract YourAbstractClass getInstance();

    @Test
    public void testThing() {
        final YourAbstractClass instance = this.getInstance();
        instance.callMethod();

        Assertions.assertTrue(instance.someProperties());
    }
}

旁边:

public class ConcreteSubclassTest extends YourAbstractClassTest {
    private final ConcreteSubclass instance = new ConcreteSubclass();

    @Override
    protected YourAbstractClass getInstance() {
        return this.instance;
    }

    @Test
    public void moreTesting() {
        this.instance.implementationSpecificMethod();
    }
}

您还可以在测试 class 中为其创建一个 dummy subclass:

public class AbstractClassTest {
    private final AbstractClass instance = new AbstractClass() {
        @Override
        public void abstractMethod() {
            throw new UnsupportedOperationException();
        }
    }

    @Test
    public void testThing() {
        this.instance.concreteMethod();
        // Just make sure this doesn't ever go near the
        // methods you dummied up above...
    }
}