单元测试抽象类和/或接口

Eri*_*tas 8 inheritance unit-testing interface visual-studio-2010

我正在尝试在Visual Studio 2010中的当前项目上开始使用单元测试.但是,我的类结构包含许多接口和抽象类继承关系.

如果两个类是从同一个抽象类或接口派生的,那么我希望能够在它们之间共享测试代码.我不确定该怎么做.我想我为每个要测试的接口创建了一个测试类,但我不确定将具体类提供给适用的单元测试的正确方法.


更新

好的,这是一个例子.假设我有一个接口IEmployee,它由一个抽象类Employee实现,然后由两个具体的类Worker和Employee继承.(代码如下)

现在说我想创建适用于所有IEmployees或Employees的测试.或者为特定类型的员工创建特定测试.例如,我可能想断言将IEmployee.Number设置为小于零的数字,因为任何IEmployee实现都会引发异常.我更喜欢从任何IEmployee的角度编写测试,然后能够在IEmployee的任何实现上使用测试.

这是另一个例子.我可能还想断言,将任何员工的休假时间设置为小于零的值和错误.然而,我可能还希望有不同的测试适用于特定的Employee特定版本.假设我想测试如果工作人员提供超过14天的假期,那么工作人员会抛出异常,但最多可以提供36名经理.

public interface IEmployee
{
    string Name {get; set;}
    int Number {get; set;}
}


public abstract class Employee:IEmploee
{
    string Name {get; set;}
    int Number {get;set;}
    public abstract int VacationTime(get; set;)
}


public abstract class Worker:IEmployee
{
    private int v;

    private int vTime;
    public abstract int VacationTime
    {
       get
       {
         return VTime;
       }
       set
      { 
         if(value>36) throw new ArgumentException("Exceeded allowed vaction");
         if(value<0)throw new ArgumentException("Vacation time must be >0");
         vTime= value;
       }
    }


    public void DoSomWork()
    {
      //Work
    }
}


public abstract class Manager:IEmployee
{
    public abstract int VacationTime
    {
       get
       {
         return VTime;
       }
       set
      { 
         if(value>14) throw new ArgumentException("Exceeded allowed vaction");
         if(value<0)throw new ArgumentException("Vacation time must be >0");
         vTime= value;
       }
    }

  public void DoSomeManaging()
  {
      //manage
  }

}
Run Code Online (Sandbox Code Playgroud)

所以我想我正在寻找的工作流程将允许我嵌套单元测试.因此,例如,当我测试Manager类时,我想首先测试它是否通过了Employee和IEmployee测试,然后测试特定的成员,例如DoSomeManaging().

小智 6

我想我知道你的意思.我遇到过同样的问题.

我的解决方案是创建一个用于测试的层次结构.我将使用您展示的相同示例.

首先,为基本IEmployee设置一个抽象测试类.

它有两个主要的东西:i.您想要的所有测试方法.II.一种抽象方法,返回IEmployee的所需实例.

[TestClass()]
public abstract class IEmployeeTests
{
    protected abstract GetIEmployeeInstance();

    [TestMethod()]
    public void TestMethod1()
    {
    IEmployee target = GetIEmployeeInstance();
    // do your IEmployee test here
    }

}
Run Code Online (Sandbox Code Playgroud)

其次,您为IEmployee的每个实现都有一个测试类,实现抽象方法并提供适当的IEmployee实例.

[TestClass()]
public class WorkerTests : IEmployeeTests
{

    protected override GetIEmployeeInstance()
    {
        return new Worker();
    }

}

[TestClass()]
public class ManagerTests : IEmployeeTests
{

    protected override GetIEmployeeInstance()
    {
        return new Manager();
    }

}
Run Code Online (Sandbox Code Playgroud)

您可以看到所有内容都按预期工作,VS为TestView窗口中的每个WorkerTests和ManagerTests类提供了预期的测试方法.您可以运行它们并获得IEmployee接口的每个实现的测试结果,只需在基本IEmployeeTests类中创建测试.

您始终可以为派生的WorkerTests和ManagerTests类添加特定测试.

现在的问题是,实现多个接口的类怎么样,让我们​​说EmployedProgrammer?

public EmployedProgrammer : IEmployee, IProgrammer
{
}
Run Code Online (Sandbox Code Playgroud)

我们在C#中没有多重继承,所以这不是一个选项:

[TestClass()]
public EmployedProgrammerIEmployeeTests : IEmployeeTests, IProgrammerTests
{
     // this doesn't compile as IEmployeeTests, IProgrammerTests are classes, not interfaces
}
Run Code Online (Sandbox Code Playgroud)

对于此方案,解决方案是具有以下测试类:

[TestClass()]
public EmployedProgrammerIEmployeeTests : IEmployeeTests
{
    protected override GetIEmployeeInstance()
    {
        return new EmployedProgrammer();
    }
}

[TestClass()]
public EmployedProgrammerIProgrammerTests : IProgrammerTests
{
    protected override GetIProgrammerInstance()
    {
        return new EmployedProgrammer();
    }
}
Run Code Online (Sandbox Code Playgroud)

[TestClass()]
public abstract class IProgrammerTests
{
    protected abstract GetIProgrammerInstance();

    [TestMethod()]
    public void TestMethod1()
    {
        IProgrammer target = GetIProgrammerInstance();
        // do your IProgrammerTest test here
    }

}
Run Code Online (Sandbox Code Playgroud)

我用这个效果很好.希望能帮助到你.

问候,何塞