我是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的调用,并且只对我忠诚。这是不正确的?目前我因为IsAdministrator属性中的依赖项而遇到异常。
有人可以解释我如何在这里实现我的目标吗?
答案 0 :(得分:11)
在我跳到此之前的一个简短说明。通常,您希望避免使用“严格”模拟,因为它会进行脆弱的测试。如果发生任何未明确告诉Rhino发生的事情,严格模拟将抛出异常。另外我认为当你打电话来创建一个模拟时,你可能会误解Rhino正在做什么。可以将其视为自定义对象,该对象可以派生自或实现您定义的System.Type。如果你自己做了,它会是这样的:
public class FakeUserType: User
{
//overriding code here
}
由于IsAdministrator可能只是User类型的公共属性,因此无法在继承类型中覆盖它。
就您的问题而言,有多种方法可以解决这个问题。您可以将IsAdministrator实现为用户类的虚拟属性,如下所述aaronjensen:
public class User
{
public virtual Boolean IsAdministrator { get; set; }
}
这是一种正常的方法,但前提是您计划从User类继承。此外,如果你不想在这个类上伪造其他成员,他们也必须是虚拟的,这可能不是理想的行为。
实现此目的的另一种方法是使用接口。如果它真的是你想要Mock的User类,那么我将从中提取一个接口。上面的例子看起来像这样:
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
}
如果你想使用dependency injection and IOC,你可以获得更多的爱好者,但基本原则是全面的。通常,您希望您的类依赖于接口而不是具体的实现。
我希望这会有所帮助。我现在已经在一个重大项目上使用RhinoMocks很长时间了,所以不要犹豫,问我关于TDD和嘲笑的问题。
答案 1 :(得分:1)
确保IsAdministrator是虚拟的。
另外,请务必调用_mocks.ReplayAll()
答案 2 :(得分:0)
_mocks.ReplayAll()什么都不做。这只是因为你使用不计数的SetupResult.For()。使用Expect.Call()确保您的代码能够正常运行。