2012-01-19 34 views
7

我正在使用PostSharp方法属性对我的WCF服务进行授权和审计。它正常工作,但现在我试图让我的单元测试使用该属性,并努力寻找一种方法来模拟和注入属性的属性。模拟PostSharp属性的最简单方法

我的属性如下。

[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的使用。

+0

那么分配给属性是什么?实际的对象,还是他们是空的? –

+1

不,它们不为空。 _kernel.Inject(this)调用是设置两个属性对象的内容。我试图用我的单元测试做的是改变ninject内核用来设置它们的对象,那就是不工作的那一点。 – sipwiz

+0

对,所以你期望Mock对象在那里,但是它是仍然显示出来的“真实”对象? –

回答

1

而不是使用您的属性[进样]属性,重新定义它们是这样的:

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); 
+0

这非常接近我最终做的事情。唯一的区别是不用调用内核。获取每个属性,我在PostSharp OnEntry方法的开始处调用kernel.Inject。而且我也做了内核。结合我的单元测试初始化​​。 – sipwiz