2010-03-29 11 views
5

Piszę niektóre testy jednostkowe dla metody rozszerzenia, którą napisałem na IPrincipal. Aby pomóc, stworzyłem kilka klas pomocniczych (niektóre kodu dla nie-wdrożonych członków interfejsów został pominięty dla zwięzłość):Jak utworzyć kod pośredniczący testów jednostkowych dla interfejsu zawierającego element tylko do odczytu?

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

Jednakże, obiekt w interfejsie IIdentityName jest tylko do odczytu (interfejs IIDentity określa getter, ale nie ustawia dla właściwości Name).

Jak ustawić właściwość Nazwa w moim obiekcie pośredniczącym do celów testowych, jeśli interfejs zdefiniował go jako właściwość tylko do odczytu?

+0

Konstruktor? tj. "IIdentityStub" będzie miał sparametryzowany konstruktor, który bierze Name jako parametr. – shahkalpesh

+0

Czy Twój "BZZZT" odnosi się do błędu kompilacji? Byłem w stanie skompilować twoją próbkę w porządku (w/średnikach na własności Tożsamości). – micahtan

+0

@micahtan: Tak, ale kiedy spróbujesz napisać test przeciwko niemu i ustawić wartość "Name" w teście, kompilator będzie narzekał, że 'Name' jest tylko do odczytu, ponieważ właściwość' Name' w ' IIDentity' nie ma zdefiniowanego settera. –

Odpowiedz

3

Używasz funkcji auto-właściwości C#, ale zamiast tego powinieneś udać się do trasy ręcznej i utworzyć pole zaplecza dla tej właściwości. Po utworzeniu pola zaplecza można ustawić jego wartość w konstruktorze (lub uczynić z niego pole publiczne i ustawić je po obiekcie, ale jest to nieco brzydsze).

public class IIdentityStub : IIdentity{ 
    private string _name; 

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

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

A jeśli wartości nie można ustawić za pomocą konstruktora, masz problem z projektem. –

+0

Doskonale, dzięki. –

+0

@Robert Harvey: Nie ma problemu, proszę pana. –

1

Polecam przy użyciu biblioteki jak Mock NMock

+1

To prawda, ale pomyślałem, że najpierw lepiej nauczę się pisać własne kody pośredniczące. –

2

zgadzam się z juharr - używać ramy szyderczy/izolacji. Polecam Moq.

Poniższa wypisze "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: Ale jeśli chcesz zrobić to ręcznie ...

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

(Powyższe nie test jednostkowy, tylko przykład zwiniętych ręcznie kodów z użyciem zastrzyku zależności).