2010-06-25 10 views
20

Par exemple, il y a une interface IMyInterface, et trois classes soutiennent cette interface: Dans la façon la plus simpleComment testez-vous l'unité d'une interface?

class A : IMyInterface 
{ 
} 

class B : IMyInterface 
{ 
} 

class C : IMyInterface 
{ 
} 

, je pourrais écrire trois classe de test: ATest, btest, CTest et les tester séparément. Cependant, comme ils prennent en charge la même interface, la plupart des codes de test sont identiques, il est difficile à maintenir. Comment puis-je utiliser une méthode simple et facile pour tester une interface prise en charge par une classe différente?

(previously asked on the MSDN forums)

Répondre

17

Pour tester une interface avec des tests communs quelle que soit l'implémentation, vous pouvez utiliser un scénario de test abstrait, puis créer des instances concrètes du scénario de test pour chaque implémentation de l'interface. . Le scénario de test abstrait (base) effectue les tests neutres d'implémentation (vérification du contrat d'interface) tandis que les tests concrets prennent en charge l'instanciation de l'objet à tester et exécutent tous les tests spécifiques à l'implémentation.

3

pourrait créer des méthodes qui prennent un paramètre de type IMyInterface et ont les méthodes d'essai réels appellent simplement les méthodes qui passent dans les différentes classes concrètes.

2

Vous ne testez pas l'interface directement, mais vous pouvez écrire une classe abstraite qui teste le contrat qu'une implémentation particulière doit étendre. Un test d'une classe concrète étend alors la classe abstraite

37

Si vous souhaitez exécuter les mêmes tests contre différents de votre interface implémenteurs en utilisant NUnit comme exemple:

public interface IMyInterface {} 
class A : IMyInterface { } 
class B : IMyInterface { } 
class C : IMyInterface { } 

public abstract class BaseTest 
{ 
    protected abstract IMyInterface CreateInstance(); 

    [Test] 
    public void Test1() 
    { 
     IMyInterface instance = CreateInstance(); 
     //Do some testing on the instance... 
    } 

    //And some more tests. 
} 

[TestFixture] 
public class ClassATests : BaseTest 
{ 
    protected override IMyInterface CreateInstance() 
    { 
     return new A(); 
    } 

    [Test] 
    public void TestCaseJustForA() 
    { 
     IMyInterface instance = CreateInstance(); 
     //Do some testing on the instance... 
    } 

} 

[TestFixture] 
public class ClassBTests : BaseTest 
{ 
    protected override IMyInterface CreateInstance() 
    { 
     return new B(); 
    } 
} 

[TestFixture] 
public class ClassCTests : BaseTest 
{ 
    protected override IMyInterface CreateInstance() 
    { 
     return new C(); 
    } 
} 
+0

C'est un bon exemple de la bonne réponse. – Chetan

+1

+1 Bonne réponse! De nos jours NUnit prend en charge les classes de test génériques et l'attribut TestFixture peut être utilisé pour fournir les types spécifiques à utiliser lorsque le test est exécuté. J'ai écrit un [post de blog] (http://softwareonastring.com/2015/03/22/testing-every-implementer-of-an-interface-with-the-same-tests-using-nunit) sur la façon de tester chaque implémenteur d'une interface présentant ces fonctionnalités. –

+0

Réponse élégante et concise ... –

0

Si vous utilisez NUnit, vous pouvez ensuite utiliser Grensesnitt:

public interface ICanAdd { 
    int Add(int i, int j); //dont ask me why you want different adders 
} 

public class winefoo : ICanAdd { 
    public int Add(int i, int j) 
    { 
     return i + j; 
    } 
} 

interface winebar : ICanAdd { 
    void FooBar() ; 
} 

public class Adder1 : winebar { 
    public int Add(int i, int j) { 
     return i + j; 
    } 
    public void FooBar() {} 
} 

public class Adder2 : ICanAdd { 
    public int Add(int i, int j) { 
     return (i + 12) + (j - 12); //yeeeeeaaaah 
    } 
} 

[InterfaceSpecification] 
public class WithOtherPlugins : AppliesToAll<ICanAdd> 
{ 
    [TestCase(1, 2, 3)] 
    [TestCase(-1, 2, 1)] 
    [TestCase(0, 0, 0)] 
    public void CanAddOrSomething(int x, int y, int r) 
    { 
     Assert.AreEqual(subject.Add(x, y), r); 
    } 

    [TestCase(1, 2, Result = 3)] 
    [TestCase(-1, 2, Result = 1)] 
    [TestCase(0, 0, Result = 0)] 
    public int CannAddOrSomethingWithReturn(int x, int y) { 
     return subject.Add(x, y); 
    } 
}