Im Posting
Code Contracts für Interfaces und abstrakte Klassen habe ich beschrieben, dass Code Contracts die Möglichkeit bieten, mit einem Interface nicht nur syntaktische sondern auch semantische Vorgaben zu definieren. Eine wenn auch nicht ganz so einfache Alternative dazu ist das Bereitstellen von Unit-Tests für Interfaces.
Da diese das Interface nicht instanziieren können, verwenden solche Unit-Tests eine abstrakte Factory-Method, womit sie die Erstellung der konkreten Implementierung an ihre Subklassen weiterdelegieren. Das nachfolgend dargestellte Beispiel demonstriert dies. Für das Interface
IStarShip wird dazu zunächst festgelegt, dass für einen negativen Übergabeparameter eine
TransporterException auszulösen ist. Der abstrakte Unit-Test
IStarShipTest überprüft dies. Im Zuge dessen wird die abstrakte Methode
create zum erzeugen einer Instanz von
StarShip verwendet. Die Implementierung dieser Methode findet sich in den Realisierung des betrachteten Interfaces. Beispielsweise erzeugt
ContitutionClassStarShipTest eine Instanz von
ContitutionClassStar , welche somit über diesen Unit-Test den für das Interface definierten Tests unterzogen wird.
public interface IStarShip
{
/// <summary>
/// Beamt die gewünschte Anzahl
/// an Personen an Board.
/// Falls ein Fehler auftritt,
/// oder persons negativ ist, wird
/// eine TransporterException
/// ausgelöst.
/// </summary>
/// <param name="persons">
/// Anzahl der zu beamenden Personen
/// </param>
void BeamUp(int persons);
}
public abstract class IStarShipTest
{
protected abstract IStarShip create();
[TestMethod]
[ExpectedException(typeof(TransporterException))]
public void TestBeamNegativePersons()
{
IStarShip ship = create();
ship.BeamUp(-1);
}
// Weitere Test-Methoden ...
}
public class ConstitutionClassShip : IStarShip
{
public void BeamUp(int persons)
{
if (persons < 0) throw new TransporterException();
}
}
[TestClass]
public class ContitutionClassStarShipTest: IStarShipTest
{
protected override IStarShip create()
{
return new ConstitutionClassShip();
}
}