2008-09-16 48 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()来确保你的代码能够做到一切正确。

相关问题