2010-03-29 5 views
5

J'écris des tests unitaires pour une méthode d'extension que j'ai écrite sur IPrincipal. Pour aider, je l'ai créé deux classes d'aide (un code pour les membres non mis en œuvre des interfaces a été omis par souci de concision):Comment créer un talon de test d'unité pour une interface contenant un membre en lecture seule?

public class IPrincipalStub : IPrincipal 
{ 
    private IIdentity identityStub = new IIdentityStub(); 

    public IIdentity Identity 
    { 
     get { return identityStub; } 
     set { identityStub = value; } 
    } 
} 

public class IIdentityStub : IIdentity 
{ 
    public string Name { get; set; } // BZZZT!!! 
} 

Cependant, la propriété Name dans l'interface IIdentity est en lecture seule (l'interface IIDentity spécifie un getter mais pas un setter pour la propriété Name).

Comment puis-je définir la propriété Name dans mon objet de raccord à des fins de test si l'interface l'a définie en tant que propriété en lecture seule?

+0

Constructeur? i.e 'IIdentityStub' aura un constructeur paramétré qui prend Name comme paramètre. – shahkalpesh

+0

Est-ce que votre "BZZZT" faisait référence à une erreur de compilation? J'ai été capable de compiler votre échantillon très bien (w/point-virgule sur la propriété Identity, c'est-à-dire). – micahtan

+0

@micahtan: Oui, mais lorsque vous essayez d'écrire un test et que vous définissez la valeur de 'Name' dans le test, le compilateur se plaindra que' Name' est en lecture seule, car la propriété 'Name' dans' IIDentity' n'a pas de setter défini. –

Répondre

3

Vous utilisez la fonction de propriétés automatiques de C#, mais vous devez utiliser la route manuelle et créer un champ de sauvegarde pour la propriété. Une fois que vous avez un champ de sauvegarde, vous pouvez définir sa valeur dans le constructeur (ou en faire un champ public et le définir après avoir l'objet, mais c'est un peu plus laid).

public class IIdentityStub : IIdentity{ 
    private string _name; 

    public IIdentityStub(string name){ 
     _name = name; 
    } 

    public string Name { get { return _name; } } 
} 
+0

Et si la valeur n'est pas réglable via le constructeur, vous avez un problème avec votre conception. –

+0

Excellent, merci. –

+0

@ Robert Harvey: Pas de problème monsieur. –

1

Je recommande d'utiliser une bibliothèque Mock comme NMock

+1

C'est vrai, mais j'ai pensé que je ferais mieux d'apprendre à écrire mes propres talons d'abord. –

2

Je suis d'accord avec juharr - utiliser un cadre moqueur/isolement. Je recommande Moq.

Ce qui suit imprimera "Robert":

using System; 
using System.Security.Principal; 
using Moq; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main() 
     { 
      var mockIdentity = new Mock<IIdentity>(); 
      var mockPrincipal = new Mock<IPrincipal>(); 

      mockIdentity.SetupGet(x => x.Name).Returns("Robert"); 
      mockPrincipal.SetupGet(x => x.Identity).Returns(mockIdentity.Object); 

      IPrincipal myStub = mockPrincipal.Object; 

      Console.WriteLine(myStub.Identity.Name); 
     } 
    } 
} 

EDIT: Mais si vous voulez le faire à la main ...

using System; 
using System.Security.Principal; 

namespace ConsoleApplication2 
{ 
    class Program 
    { 
     static void Main() 
     { 
      IIdentity identity = 
       new IdentityStub 
        { 
         Name = "Robert", 
         AuthenticationType = "Kerberos", 
         IsAuthenticated = true 
        }; 

      IPrincipal principal = new PrincipalStub(identity); 

      Console.WriteLine(principal.Identity.Name); // Robert 
      Console.WriteLine(principal.IsInRole(PrincipalStub.ValidRole)); // True 
      Console.WriteLine(principal.IsInRole("OtherRole")); // False 
     } 
    } 

    public class PrincipalStub : IPrincipal 
    { 
     public const string ValidRole = "TestRole"; 

     public PrincipalStub(IIdentity identity) 
     { 
      Identity = identity; 
     } 

     public IIdentity Identity { get; private set; } 

     public bool IsInRole(string role) 
     { 
      return role == ValidRole; 
     } 
    } 

    public class IdentityStub : IIdentity 
    { 
     public string Name { get; set; } 
     public string AuthenticationType { get; set; } 
     public bool IsAuthenticated { get; set; } 
    } 
} 

(Ce qui précède est pas une test unitaire, juste un exemple de talons roulés à la main en utilisant un peu d'injection de dépendance.)

Questions connexes