模拟PostSharp属性的最简单方法

sip*_*wiz 7 wcf unit-testing rhino-mocks ninject postsharp

我正在使用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;
     }
}
Run Code Online (Sandbox Code Playgroud)

我有一个设置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>();
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的WCF服务中,我使用PostSharp属性,如下所示:

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

在我的单元测试中,我正在使用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);
}
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是单元测试中的模拟对象永远不会被设置为属性上的属性.我做错了什么或反过来有没有更好的方法对PostSharp属性进行单元测试?另外请记住,我真的希望尽量减少使用Ninject DI.

Kai*_*i G 1

不要在属性上使用 [Inject] 属性,而是像这样重新定义它们:

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

    public UserSessionDataLayer _userSessionDataLayer { get { return _kernel.Get<UserSessionDataLayer>(); } }
Run Code Online (Sandbox Code Playgroud)

另外,在您的测试方法中,您需要重新绑定(另请注意,您在第一次绑定中使用具体类型 ServiceAuthToken 而不是接口 IServiceAuthToken):

MyKernel.Kernel.Rebind<IServiceAuthToken>().ToConstant(mockServiceAuthToken);
MyKernel.Kernel.Rebind<UserSessionDataLayer>().ToConstant(mockUserSessionDataLayer);
Run Code Online (Sandbox Code Playgroud)