Самый простой способ подделать свойства атрибута PostSharp - PullRequest
7 голосов
/ 19 января 2012

Я использую атрибут метода PostSharp для авторизации и аудита в моей службе WCF. Он работает нормально, но сейчас я пытаюсь заставить мои модульные тесты работать с атрибутом и пытаюсь найти способ смоделировать и внедрить свойства атрибута.

Мой атрибут, как показано ниже.

[Serializable]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class AuthoriseAndAuditAttribute : OnMethodBoundaryAspect
{
    private static ILog logger = AppState.logger;

    private static Ninject.IKernel _kernel = MyKernel.Kernel;

    private UserRoleTypesEnum _requiredRole = UserRoleTypesEnum.None;

    [Inject]
    public IServiceAuthToken _serviceAuthToken { get; set; }

    [Inject]
    public UserSessionDataLayer _userSessionDataLayer { get; set; }

    public AuthoriseAndAuditAttribute(UserRoleTypesEnum role = UserRoleTypesEnum.None)
    {
        _requiredRole = role;
        _kernel.Inject(this);
    }

    public override void OnEntry(MethodExecutionArgs args)
    {
        // Get the user's session from cookie.
        UserSession userSession = GetUserSession();

        // Check that user is in the required role.
        bool isAuthorised = (_requiredRole == UserRoleTypesEnum.None || (userSession != null && userSession.Roles.Contains(_requiredRole)));

        if (!isAuthorised)
        {
            logger.Warn("Not authorised for " + args.Method.Name + ".");
            throw new UnauthorizedAccessException();
        }
        else if (userSession != null)
        {
            Thread.CurrentPrincipal = new MyPrincipal(userSession);
        }
    }

    private UserSession GetUserSession()
    {
        if (_serviceAuthToken != null)
        {
            string sessionID = _serviceAuthToken.GetSessionID();

             if (!sessionID.IsNullOrBlank())
             {
                 return _userSessionDataLayer.GetForSessionID(sessionID);
             }
         }

         return null;
     }
}

У меня есть одноэлементный класс, устанавливающий ядро ​​Ninject:

public class MyKernel
{
    public static StandardKernel Kernel { get; set; }

    static MyKernel()
    {
        Kernel = new StandardKernel();
        Kernel.Bind<IServiceAuthToken>().To<ServiceAuthToken>();
        Kernel.Bind<UserSessionDataLayer>().To<UserSessionDataLayer>();
    }
}

В моей службе WCF я использую атрибут PostSharp, как показано ниже:

[AuthoriseAndAudit(UserRoleTypesEnum.Operator)]
public JSONResult<bool> IsAliveAuthorised()
{
   return new JSONResult<bool>() { Success = true, Result = true };
}

И в моем модульном тесте я использую RhinoMocks, чтобы попытаться смоделировать два свойства DI в атрибуте.

 [TestMethod]
 public void IsAliveAuthorisedIsAuthorisedTest()
 {
     var mockServiceAuthToken = MockRepository.GenerateStrictMock<ServiceAuthToken>();
     mockServiceAuthToken.Stub(x => x.GetSessionID()).Return("x");
     var mockUserSessionDataLayer = MockRepository.GenerateStrictMock<UserSessionDataLayer>();
     mockUserSessionDataLayer.Stub(x => x.GetForSessionID(Arg<string>.Is.Anything)).Return(new UserSession());

     MyKernel.Kernel.Bind<ServiceAuthToken>().ToConstant(mockServiceAuthToken);
     MyKernel.Kernel.Bind<UserSessionDataLayer>().ToConstant(mockUserSessionDataLayer);

     var service = new MyService();
     Assert.IsTrue(service.IsAliveAuthorised().Result);
}

Проблема, с которой я столкнулся, заключается в том, что фиктивные объекты в модульном тесте никогда не будут установлены в качестве свойств атрибута. Что я делаю неправильно или, наоборот, есть ли лучший способ провести модульное тестирование атрибута PostSharp? Также, имея в виду, я действительно хочу свести к минимуму использование Ninject DI до минимума.

1 Ответ

1 голос
/ 07 февраля 2012

Вместо использования атрибута [Inject] в ваших свойствах, переопределите их следующим образом:

    public IServiceAuthToken _serviceAuthToken { get { return _kernel.Get<IServiceAuthToken>(); } }

    public UserSessionDataLayer _userSessionDataLayer { get { return _kernel.Get<UserSessionDataLayer>(); } }

Кроме того, в вашем методе тестирования вам необходимо повторно привязать (обратите внимание также, что вы использовали конкретныйвведите ServiceAuthToken в первой привязке вместо интерфейса IServiceAuthToken):

MyKernel.Kernel.Rebind<IServiceAuthToken>().ToConstant(mockServiceAuthToken);
MyKernel.Kernel.Rebind<UserSessionDataLayer>().ToConstant(mockUserSessionDataLayer);
...