Mock IIdentity和IPrincipal

时间:2008-10-02 14:19:22

标签: mocking iprincipal

我只想问一下在单元测试中提供这些对象的更好方法。

在我的单元测试中,我正在测试CSLA对象。 CSLA对象在内部使用一个属性和一个ApplicationUser对象的方法。 ApplicationUser继承自IPrincipal。 属性是: 1)ApplicationContext.User.IsInRole(...) - 该方法是IPrincipal的一部分 2)ApplicationContext.User.Identity.Name - 名称是IIdentity的属性,它是ApplicationUser的一部分,也就是IPricipal

我的测试示例(使用RhinoMock):

public void BeforeTest()
{
   mocks = new MockRepository();
   IPrincipal mockPrincipal = mocks.CreateMock<IPrincipal>();
   ApplicationContext.User = mockPrincipal;
   using (mocks.Record()) {
      Expect.Call(mockPrincipal.IsInRole(Roles.ROLE_MAN_PERSON)).Return(true);
      Expect.Call(mockPrincipal.Identity.Name).Return("ju"); //doesn't work!!!! return null ref exc
   }
}

我对第二个值(身份名称)有轻微问题。我试图模仿它,但有问题将模拟的IIdentity分配给ApplicationUser,因为它是在内部完成的。 我被告知要自己创建一些IIPrincipal(包括IIdentity),而不是嘲笑它。哪个可以肯定。不确定这是否可以作为Stub使用?

那么你能告诉我如何处理IPrincipal和IIdentity吗?任何建议都是最受欢迎的。

2 个答案:

答案 0 :(得分:10)

您获得空引用错误的原因是因为IPrincipal.Identity为空;它尚未在您的模拟IPrincipal中设置。调用.NameIdentity会导致您的例外。

正如卡尔顿指出的那样,答案是模仿IIdentity ,并将其设置为为其Name属性返回“ju”。然后,您可以告诉IPrincipal.Identity返回模拟IIdentity

这是你的代码扩展(使用Rhino Mocks而不是Stubs):

public void BeforeTest()
{
   mocks = new MockRepository();
   IPrincipal mockPrincipal = mocks.CreateMock<IPrincipal>();
   IIdentity mockIdentity = mocks.CreateMock<IIdentity>();
   ApplicationContext.User = mockPrincipal;
   using (mocks.Record()) 
   {
      Expect.Call(mockPrincipal.IsInRole(Roles.ROLE_MAN_PERSON)).Return(true);
      Expect.Call(mockIdentity.Name).Return("ju"); 
      Expect.Call(mockPrincipal.Identity).Return(mockIdentity);
   }
}

答案 1 :(得分:4)

以下是我用来返回测试用户的代码(使用Stubs):

    [SetUp]
    public void Setup()
    {
        var identity = MockRepository.GenerateStub<IIdentity>();
        identity.Stub(p => p.Name).Return("TestUser").Repeat.Any();
        var principal = MockRepository.GenerateStub<IPrincipal>();
        principal.Stub(p => p.Identity).Return(identity).Repeat.Any();

        Thread.CurrentPrincipal = principal;
    }

我在其他代码中有linq,所以我使用var类型作为变量;如果需要,只需替换正确的类型(IPrincipal,IIdentity)。