2012-01-19 9 views
7

Sto utilizzando un attributo del metodo PostSharp per eseguire l'autorizzazione e il controllo sul servizio WCF. Funziona correttamente, ma ora sto cercando di far funzionare i miei test unitari con l'attributo e sto facendo fatica a trovare un modo per prendere in giro e iniettare le proprietà sull'attributo.Il modo più semplice per simulare le proprietà dell'attributo PostSharp

Il mio attributo è il seguente.

[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; 
    } 
} 

devo impostare una classe Singleton il kernel 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>(); 
    } 
} 

Nel mio servizio WCF io uso l'attributo PostSharp come di seguito:

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

E nella mia unità di prova I Sto usando RhinoMocks per provare a prendere in giro le due proprietà DI nell'attributo.

[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); 
} 

Il problema che ho è l'oggetti mock nel test di unità non sono mai fine per essere impostato come le proprietà dell'attributo. Che cosa sto sbagliando o viceversa c'è un modo migliore per eseguire il test delle unità su un attributo PostSharp? Tenendo presente, voglio davvero ridurre al minimo l'uso di Ninject DI.

+0

Quindi cosa viene assegnato alle proprietà? Gli oggetti reali o sono nulli? –

+1

No, non sono nulli. La chiamata _kernel.Inject (this) è ciò che imposta i due oggetti proprietà. Quello che sto cercando di fare con il mio unit test è cambiare gli oggetti che il kernel ninject usa per impostarli e questo è il bit che non funziona. – sipwiz

+0

Giusto, quindi ti stai aspettando che gli oggetti Mock siano lì, ma invece sono gli oggetti "reali" che vengono ancora visualizzati? –

risposta

1

Invece di usare l'attributo [Inject] sulle proprietà, li ridefinire in questo modo:

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

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

Inoltre, nel metodo di prova è necessario ri-bind (nota anche che si stava utilizzando il tipo di cemento ServiceAuthToken nel primo binding invece dell'interfaccia IServiceAuthToken):

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

Questo è molto vicino a quello che ho finito per fare. L'unica differenza è invece di chiamare il kernel. Procedere su ogni proprietà che chiamo kernel.Inject all'inizio del metodo PostSharp OnEntry. E faccio anche il kernel. Restituisci l'inizializzazione del test dell'unità. – sipwiz