2010-03-29 18 views
5

Ich schreibe einige Komponententests für eine Erweiterungsmethode, die ich auf IPrincipal geschrieben habe. Zur Unterstützung, ich habe ein paar Hilfsklassen (ein Code für nicht-implementierten Mitglieder der Schnittstellen der Kürze halber weggelassen wurde) erstellt:Wie erstellen Sie einen Unit-Test-Stub für eine Schnittstelle mit einem schreibgeschützten Member?

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!!! 
} 

jedoch die Name Eigenschaft in der IIdentity Schnittstelle ist schreibgeschützt (Die Schnittstelle IIDentity gibt einen Getter, aber keinen Setter für die Name-Eigenschaft an.

Wie kann ich die Name-Eigenschaft in meinem Stub-Objekt für Testzwecke festlegen, wenn die Schnittstelle es als schreibgeschützte Eigenschaft definiert hat?

+0

Konstruktor? "IIdentityStub" hat einen parametrisierten Konstruktor, der Name als Parameter akzeptiert. – shahkalpesh

+0

Hat sich Ihr "BZZZT" auf einen Kompilierungsfehler bezogen? Ich konnte Ihr Beispiel problemlos kompilieren (mit Semikolons auf der Identity-Eigenschaft). – micahtan

+0

@micahtan: Ja, aber wenn Sie versuchen, einen Test dagegen zu schreiben, und den Wert von 'Name' im Test setzen, wird der Compiler beschweren, dass' Name' schreibgeschützt ist, weil die 'Name' Eigenschaft in' IIDentity hat keinen definierten Setter. –

Antwort

3

Sie verwenden die Funktion für automatische Eigenschaften von C#, aber stattdessen sollten Sie die manuelle Route verwenden und ein Hintergrundfeld für die Eigenschaft erstellen. Sobald Sie ein Backing-Feld haben, können Sie seinen Wert im Konstruktor festlegen (oder es zu einem öffentlichen Feld machen und es setzen, nachdem Sie das Objekt haben, aber das ist ein bisschen hässlicher).

public class IIdentityStub : IIdentity{ 
    private string _name; 

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

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

Und wenn der Wert nicht über den Konstruktor einstellbar ist, haben Sie ein Problem mit Ihrem Design. –

+0

Ausgezeichnet, danke. –

+0

@ Robert Harvey: Kein Problem, Sir. –

1

Ich empfehle eine Mock-Bibliothek wie NMock

+1

Stimmt, aber ich dachte, ich sollte besser lernen, zuerst meine eigenen Stubs zu schreiben. –

2

ich mit juharr zustimmen - verwenden, um einen spöttischen/Isolation Rahmen. Ich würde empfehlen Moq.

Im Folgenden wird gedruckt "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: Aber wenn Sie es von Hand zu tun ...

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; } 
    } 
} 

(Die obige ist nicht ein Unit-Test, nur ein Beispiel für handgerollte Stubs mit ein bisschen Abhängigkeits-Injektion.)