2010-03-10 15 views
40

Sono abbastanza nuovo da usare moq. Sono nella creazione di alcuni casi di test di unità per HttpModule e tutto funziona bene fino a quando ho colpito una proprietà static come segueProprietà statica fittizia con moq

this.applicationPath = (HttpRuntime.AppDomainAppVirtualPath.Length > 1) ? HttpRuntime.AppDomainAppVirtualPath : String.Empty; 

Non so come creare schernisce per static di classe e proprietà come HttpRuntime.AppDomainAppVirtualPath. Il context, request e response sono stati presi in giro bene con il codice di esempio che ottengo dal moq. Apprezzerò se qualcuno mi può aiutare su questo.

risposta

57

Moq non può falsificare membri statici.

Come soluzione è possibile creare una classe wrapper (Pattern adattatore) che trattiene la proprietà statica e falsi i suoi membri.
Per esempio:

public class HttpRuntimeWrapper 
{ 
    public virtual string AppDomainAppVirtualPath 
    { 
     get 
     { 
      return HttpRuntime.AppDomainAppVirtualPath; 
     } 
    } 
} 

Nel codice di produzione è possibile accedere a questa classe, invece di HttpRuntime e falso quest'affare:

[Test] 
public void AppDomainAppVirtualPathTest() 
{ 
    var mock = new Moq.Mock<HttpRuntimeWrapper>(); 
    mock.Setup(fake => fake.AppDomainAppVirtualPath).Returns("FakedPath"); 

    Assert.AreEqual("FakedPath", mock.Object.AppDomainAppVirtualPath); 
} 

Un'altra soluzione è quella di utilizzare framework di isolamento (come Typemock Isolator) in cui si può simulare classi e membri statici.
Per esempio:

Isolate.WhenCalled(() => HttpRuntime.AppDomainAppVirtualPath) 
     .WillReturn("FakedPath"); 

Disclaimer - Io lavoro in Typemock

+5

Quando si chiede di Moq, suggerire un prodotto comico è un po 'fuori. – Finglas

+34

Perché? È un'opzione. L'avvolgimento statico è migliore, ma conoscere le opzioni è sempre una buona cosa. –

+2

Chiede una soluzione su come farlo con Moq. Ecco perchè. – Finglas

10

Non puoi MOQ metodi statici con Moq.

Questa non è una cosa negativa in realtà, i metodi e le classi statiche hanno il loro posto ma per la logica rendono difficili i test di unità. Naturalmente li incontrerai quando usi altre librerie. Per aggirare questo problema è necessario scrivere un adapter (wrapper) attorno al codice statico e fornire un'interfaccia. Per esempio:

// Your static class - hard to mock 
class StaticClass 
{ 
    public static int ReturnOne() 
    { 
     return 1; 
    } 
} 

// Interface that you'll use for a wrapper 
interface IStatic 
{ 
    int ReturnOne(); 
} 

nota, ho ommited la classe concreta che utilizza IStatic per il codice di produzione. Tutto sarebbe una classe che utilizza IStatic e il tuo codice di produzione farebbe uso di questa classe, piuttosto che StaticClass sopra.

Poi, con Moq:

var staticMock = new Mock<IStatic>(); 
staticMock.Setup(s => s.ReturnOne()).Returns(2); 
+2

@Yasser hai interrotto l'esempio di codice, sto ripristinando la tua modifica. – Finglas

3

Come accennato nelle risposte precedenti, non è possibile utilizzare MoQ sui metodi statici, e se è necessario, il vostro colpo migliore è creare un involucro attorno alla statica classe.

Tuttavia, qualcosa che ho scoperto di recente è lo Moles project. Dalla homepage; "Moles consente di sostituire qualsiasi metodo .NET con un delegato. Moles supporta metodi statici o non virtuali." Potrebbe essere utile per la tua situazione attuale.

+0

Interessante, lo verificherà. – Finglas

+0

Non utilizzare Moles. In primo luogo, aggiunge un sacco di mal di testa e rallenta drammaticamente i tempi di costruzione. In secondo luogo, è stato sostituito poiché questo commento è stato originariamente pubblicato dal più recente framework di simulazione di Microsoft. In terzo luogo, non è compatibile con VS2012 (che utilizza il framework più recente) ed è un mal di testa qui al lavoro perché abbiamo molti test scritti con Moles qui che devono essere de-Molesified prima di poter essere aggiornati. La simulazione di metodi statici è allettante (specialmente per il codice legacy), ma IMO se possibile, è meglio scrivere semplicemente il codice per essere più facile da testare. –

+0

Beh, certo, ma la domanda riguardava la classe HttpRuntime che molti di noi non possono modificare, e in quelle circostanze la necessità di simulare in qualche modo metodi/proprietà statici è inevitabile. – haughtonomous

2

La soluzione migliore che ho trovato finora è Teleak JustMock - sfortunatamente solo la versione a pagamento consente di deridere la statica.

Mentre l'idea di avvolgere la statica è buona, non si può sempre farlo.Se si desidera testare del codice che utilizza già alcune classi statiche, non è sempre possibile uscire e utilizzare un wrapper. In questo caso, JustMock sembra una soluzione ragionevole e probabilmente lo userò su alcune soluzioni nel prossimo futuro.

1

È possibile utilizzare Microsoft Fakes per questo. Risolverà definitivamente il problema. Fare riferimento a https://msdn.microsoft.com/en-us/library/hh549175.aspx

+1

Sebbene questo collegamento possa rispondere alla domanda, è sempre bene specificare i dettagli importanti anche nella domanda (il collegamento potrebbe non essere valido). – BDL