我是 RhinoMocks 的新手,除了引擎盖下发生的事情之外,还试图掌握语法。

我有一个用户对象,我们称它为 User,它有一个名为 IsAdministrator 的属性。 IsAdministrator 的值通过检查用户安全权限的另一个类进行评估,并根据这些权限返回 true 或 false。我试图模拟这个 User 类,并伪造 IsAdministrator 的返回值以隔离一些单元测试。

这是我目前正在做的事情:

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

    // do something with my User object
}

现在,我期待 Rhino 会“伪造”对属性 getter 的调用,然后将 true 返回给我。这不正确吗?目前,由于 IsAdministrator 属性中的依赖关系,我遇到了异常。

有人可以解释我如何在这里实现我的目标吗?

最佳答案

在我开始之前的一个快速说明。通常,您希望避免使用“严格”模拟,因为它会使测试变得脆弱。如果发生任何您没有明确告诉 Rhino 会发生的事情,严格模拟将抛出异常。此外,我认为您在调用创建模拟时可能会误解 Rhino 正在做什么。将其视为源自或实现您定义的 System.Type 的自定义对象。如果你自己做,它看起来像这样:

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

由于 IsAdministrator 可能只是 User 类型的公共(public)属性,因此您无法在继承类型中覆盖它。

就您的问题而言,您可以通过多种方式处理此问题。您可以将 IsAdministrator 实现为用户类上的虚拟属性,如下所述:
public class User
{
    public virtual Boolean IsAdministrator { get; set; }
}

这是一个不错的方法,但前提是您计划从您的 User 类继承。此外,如果你不想在这个类上伪造其他成员,他们也必须是虚拟的,这可能不是你想要的行为。

实现此目的的另一种方法是使用接口(interface)。如果它确实是您想要 Mock 的 User 类,那么我会从中提取一个接口(interface)。你上面的例子看起来像这样:
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
}

如果你愿意,你可以通过使用 aaronjensen 变得更漂亮,但基本原理是完全相同的。通常你希望你的类依赖于接口(interface)而不是具体的实现。

我希望这有帮助。我已经在一个主要项目中使用 RhinoMocks 很长时间了,所以不要犹豫,问我关于 TDD 和模拟的问题。

关于tdd - RhinoMocks : Correct way to mock property getter,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/78389/

10-16 19:23