Mock IIdentity и IPrincipal

Я просто хочу спросить, что лучше всего подходит для поставки этих объектов в моих модульных тестах.

В моем unit test я тестирую объект CSLA. Объект CSLA внутренне использует одно свойство и один метод объекта ApplicationUser. ApplicationUser наследуется от IPrincipal. Свойства: 1) ApplicationContext.User.IsInRole(...) - метод является частью IPrincipal 2) ApplicationContext.User.Identity.Name - имя является свойством IIdentity, которое является частью ApplicationUser aka 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? Любое предложение приветствуется.

Ответ 1

Причина, по которой вы получаете ошибку нулевой ссылки, состоит в том, что IPrincipal.Identity имеет значение null; он еще не установлен в вашем издеваемом IPrincipal. Вызов .Name null Identity приводит к вашему исключению.

Ответ, как указал Карлтон, состоит в том, чтобы высмеять IIdentity и установить его для возврата "ju" для своего свойства Name. Затем вы можете сказать IPrincipal.Identity вернуть mock 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);
   }
}

Ответ 2

Вот код, который я использую, чтобы вернуть тестового пользователя (используя 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), если это необходимо.