2010-03-29 26 views
5

我正在爲寫在IPrincipal上的擴展方法寫一些單元測試。爲了幫助,我已經創建了幾個輔助類的(一些代碼,接口沒有實現的成員已爲簡潔起見省略):如何爲包含只讀成員的接口創建單元測試存根?

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

然而,在IIdentity接口Name屬性爲只讀( IIDentity接口爲Name屬性指定了一個getter而不是setter)。

如果接口已將其定義爲只讀屬性,如何在存根對象中設置Name屬性以用於測試目的?

+0

構造函數?即'IIdentityStub'將有一個參數化的構造函數,它將Name作爲參數。 – shahkalpesh 2010-03-29 18:05:46

+0

您的「BZZZT」引用了編譯錯誤嗎?我能夠很好地編譯你的示例(在標識屬性上帶有分號,就是這樣)。 – micahtan 2010-03-29 18:27:44

+0

@micahtan:是的,但是當您嘗試針對它編寫測試,並在測試中設置Name時,編譯器會抱怨Name是隻讀的,因爲'Name'屬性在' IIDentity'沒有定義setter。 – 2010-03-29 22:35:41

回答

3

您正在使用C#的自動屬性功能,但您應該去手動路由併爲該屬性創建一個後臺字段。一旦你有一個支持領域,你可以在構造函數中設置它的值(或者將其設置爲公共字段並在擁有該對象後進行設置,但這有點醜陋)。

public class IIdentityStub : IIdentity{ 
    private string _name; 

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

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

如果通過構造函數無法設置該值,則說明設計存在問題。 – 2010-03-29 18:11:33

+0

非常好,謝謝。 – 2010-03-29 18:21:10

+0

@羅伯特哈維:沒問題,先生。 – 2010-03-29 18:22:21

1

我建議使用一個模擬庫像NMock

+1

是的,但我想我最好先學習如何寫自己的存根。 – 2010-03-29 18:19:48

2

我同意juharr - 用嘲諷/隔離框架。我建議Moq

下將打印 「羅伯特」:

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

編輯:但是,如果你想通過做手工......

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

(以上爲一單元測試,只是使用一點依賴注入的手動存根的例子。)

相關問題