我想知道如何单元测试抽象类,以及扩展抽象类的类。

我是否应该通过扩展抽象类来测试它,去掉抽象方法,然后测试所有的具体方法?然后只测试我重写的方法,并在单元测试中测试扩展抽象类的对象的抽象方法?

我是否应该有一个抽象测试用例,可以用来测试抽象类的方法,并在测试用例中为扩展抽象类的对象扩展该类?

注意,我的抽象类有一些具体的方法。


当前回答

首先,如果抽象类包含一些具体的方法,我认为你应该这样做,考虑这个例子

 public abstract class A 

 {

    public boolean method 1
    {
        // concrete method which we have to test.

    }


 }


 class B extends class A

 {

      @override
      public boolean method 1
      {
        // override same method as above.

      }


 } 


  class Test_A 

  {

    private static B b;  // reference object of the class B

    @Before
    public void init()

      {

      b = new B ();    

      }

     @Test
     public void Test_method 1

       {

       b.method 1; // use some assertion statements.

       }

   }

其他回答

我反对“抽象”测试。我认为测试是一个具体的概念,没有抽象的概念。如果您有公共元素,请将它们放在辅助方法或类中供所有人使用。

至于测试抽象测试类,一定要问自己要测试的是什么。有几种方法,您应该找出适合您的场景的方法。您是否试图在子类中测试一个新方法?然后让您的测试只与该方法交互。测试基类中的方法吗?然后可能只针对该类有一个单独的fixture,并使用尽可能多的测试单独测试每个方法。

这是我在设置一个测试抽象类的工具时通常遵循的模式:

public abstract class MyBase{
  /*...*/
  public abstract void VoidMethod(object param1);
  public abstract object MethodWithReturn(object param1);
  /*,,,*/
}

以及我在测试中使用的版本:

public class MyBaseHarness : MyBase{
  /*...*/
  public Action<object> VoidMethodFunction;
  public override void VoidMethod(object param1){
    VoidMethodFunction(param1);
  }
  public Func<object, object> MethodWithReturnFunction;
  public override object MethodWithReturn(object param1){
    return MethodWihtReturnFunction(param1);
  }
  /*,,,*/
}

如果在我不期望它的时候调用抽象方法,测试就会失败。在安排测试时,我可以很容易地用lambdas剔除抽象方法,这些方法执行断言、抛出异常、返回不同的值等。

如果您的抽象类包含具有业务价值的具体功能,那么我通常会通过创建一个测试双存根来直接测试它,或者使用一个模拟框架来为我做这件事。我选择哪一个很大程度上取决于我是否需要编写抽象方法的特定于测试的实现。

我需要这样做的最常见的场景是当我使用模板方法模式时,例如当我正在构建某种将由第三方使用的可扩展框架时。在本例中,抽象类定义了我想要测试的算法,因此测试抽象基类比测试特定实现更有意义。

然而,我认为重要的是这些测试应该只关注真实业务逻辑的具体实现;您不应该单元测试抽象类的实现细节,因为您最终会得到脆弱的测试。

为了专门对抽象类进行单元测试,您应该出于测试目的派生它,test base.method()的结果和继承时预期的行为。

你通过调用一个方法来测试它,所以通过实现一个抽象类来测试它……

首先,如果抽象类包含一些具体的方法,我认为你应该这样做,考虑这个例子

 public abstract class A 

 {

    public boolean method 1
    {
        // concrete method which we have to test.

    }


 }


 class B extends class A

 {

      @override
      public boolean method 1
      {
        // override same method as above.

      }


 } 


  class Test_A 

  {

    private static B b;  // reference object of the class B

    @Before
    public void init()

      {

      b = new B ();    

      }

     @Test
     public void Test_method 1

       {

       b.method 1; // use some assertion statements.

       }

   }