2008-09-16 52 views
12

我是RhinoMocks的新手,除了引擎蓋下發生的事情之外,還試圖掌握語法。RhinoMocks:正確的方式來模擬屬性getter

我有一個用戶對象,我們稱它爲User,它有一個名爲IsAdministrator的屬性。 IsAdministrator的值通過另一個用於檢查用戶安全權限的類來評估,並根據這些權限返回true或false。我試圖嘲笑這個用戶類,並假冒IsAdministrator的返回值,以隔離一些單元測試。

這是我在做什麼至今:

public void CreateSomethingIfUserHasAdminPermissions() 
{ 
    User user = _mocks.StrictMock<User>(); 
    SetupResult.For(user.IsAdministrator).Return(true); 

    // do something with my User object 
} 

現在,我期待的是犀牛是要「假」調用屬性getter和剛剛回歸真實的我。這是不正確的?目前,由於IsAdministrator屬性中的依賴關係,我得到一個異常。

有人可以解釋我怎麼能在這裏實現我的目標嗎?

回答

11

一個快速的注意之前,我跳進這一點。通常情況下,您希望避免使用「嚴格」模擬,因爲它會進行脆弱的測試。如果發生任何你沒有明確告訴犀牛會發生的事情,嚴格的模擬會拋出異常。此外,我認爲您可能會誤解犀牛在創建模擬電話時所做的事情。可以把它看作是一個自定義的對象,它既可以派生出來,也可以實現你定義的System.Type。如果你自己做的,將是這樣的:

public class FakeUserType: User 
{ 
    //overriding code here 
} 

由於IsAdministrator可能只是用戶類型公共財產,你不能在繼承類型覆蓋它。

就您的問題而言,您可以通過多種方式處理此問題。你可以在你的用戶類實現IsAdministrator作爲虛擬財產所提到如下aaronjensen

public class User 
{ 
    public virtual Boolean IsAdministrator { get; set; } 
} 

這是一個不錯的辦法,但只有當你打算從你的用戶類繼承。此外,如果你不想僞造這個班的其他成員,他們也必須是虛擬的,這可能不是所期望的行爲。

另一種完成此操作的方法是通過使用接口。如果它真的是你想要模擬的用戶類,那麼我會從中提取一個接口。你上面的例子會是這個樣子:使用dependency injection and IOC

public interface IUser 
{ 
    Boolean IsAdministrator { get; } 
} 

public class User : IUser 
{ 
    private UserSecurity _userSecurity = new UserSecurity(); 

    public Boolean IsAdministrator 
    { 
     get { return _userSecurity.HasAccess("AdminPermissions"); } 
    } 
} 

public void CreateSomethingIfUserHasAdminPermissions() 
{ 
    IUser user = _mocks.StrictMock<IUser>(); 
    SetupResult.For(user.IsAdministrator).Return(true); 

    // do something with my User object 
} 

你可以得到,如果你想票友,但基本原則是一刀切相同。通常你希望你的類依賴於接口而不是具體的實現。

我希望這會有所幫助。我現在一直在使用RhinoMocks進行重要項目,所以不要猶豫,問我關於TDD和嘲笑的問題。

+1

只是需要注意的是最後一個例子需要一個`_mocks.ReplayAll()`你做的IUSER存根任何事情之前。 – 2009-10-30 00:07:11

1

確保IsAdministrator是虛擬的。

此外,一定要調用_mocks.ReplayAll()

0

_mocks.ReplayAll()什麼都不會做。這僅僅是因爲你使用SetupResult.For(),它不計數。使用Expect.Call()來確保你的代碼能夠做到一切正確。

相關問題