2009-12-30 12 views
14

Esiste un modo per simulare/falsificare l'oggetto sessione nei moduli Web ASP.Net durante la creazione dei test delle unità?Come posso simulare/falsificare l'oggetto sessione nei moduli Web ASP.Net?

Attualmente sto memorizzando i dettagli dell'utente in una variabile di sessione a cui si accede dalla mia logica aziendale.

Quando si verifica la logica della mia attività in isolamento, la sessione non è disponibile. Questo sembra indicare un cattivo design (anche se non ne sono sicuro). In primo luogo, il livello della logica di business deve accedere alle variabili di sessione?

In tal caso, come dovrei passare allo scambio dei dettagli utente con un oggetto falso per il test?

+0

vedere anche la mia risposta su questa questione - http://stackoverflow.com/a/8487847/232593 –

risposta

9

In ASP.NET, non è possibile creare un doppio di test di HttpSessionState perché è sealed. Sì, questo è un cattivo progetto da parte dei designer originali di ASP.NET, ma non c'è molto da fare al riguardo.

Questo è uno dei molti motivi per cui TDD'ers e altri operatori di SOLID hanno in gran parte abbandonato ASP.NET in favore di ASP.NET MVC e altri framework più testabili. In ASP.NET MVC, la sessione HTTP è modellata dalla classe HttpSessionStateBase astratta.

È possibile adottare un approccio simile e consentire agli oggetti di lavorare su una sessione astratta, quindi avvolgere la classe HttpSessionState reale quando si esegue l'ambiente ASP.NET. A seconda delle circostanze, potresti persino riuscire a riutilizzare i tipi da System.Web.Abstractions, ma in caso contrario, puoi definirne uno tuo.

In ogni caso, la logica aziendale è il modello di dominio e dovrebbe essere modellato indipendentemente da una particolare tecnologia di runtime, quindi direi che non dovrebbe essere l'accesso all'oggetto di sessione in primo luogo.

Se è assolutamente necessario utilizzare test raddoppia per tets unità che coinvolgono HttpSessionState, questo è ancora possibile con alcuni mock dinamiche invasive, come TypeMock o Moles, ma decorate questi portano un sacco di svantaggi (vedi this comparison of dynamic mocks).

1

I tuoi istinti sono corretti --- non dovresti accedere a parti del framework ASP.NET dalla tua logica aziendale. Ciò includerebbe la sessione.

Per rispondere alla tua prima domanda, è possibile classi statiche finte utilizzando un prodotto come Typemock Isolator, ma sarà meglio se si refactoring il codice per avvolgere l'accesso alla sessione in un'interfaccia (vale a dire, IHttpSession.) È quindi possibile simulare IHttpSession.

0

Un approccio consiste nel passare un'espressione lambda al codice che accetta una stringa (o qualche altro oggetto) come input e la utilizza per impostare l'oggetto Session o un contenitore di test.

Tuttavia, come altri hanno già detto, è una buona idea spostare l'accesso all'oggetto Session dal BLL.

1

Nei webform Asp.Net, non si può sfuggire al fatto che la voce del framework nel codice proviene da pagine aspx. Sono d'accordo che il tuo livello aziendale non dovrebbe toccare direttamente i componenti specifici di asp.net ma devi avere il contenitore di memoria di un modello e la sessione in asp.net è una buona area. Quindi, un possibile approccio è creare ISessionManager allo scopo di interagire all'interno del tuo livello aziendale. Quindi, implementa il tipo concreto usando HttpSessionState ... btw, un buon trucco è usare HttpContext.Current.Session per implementare accessors/getter da HttpSessionState. La tua prossima sfida sarebbe come collegare tutto insieme.

25

È possibile farlo con essenzialmente 4 linee di codice. Sebbene questo non parli del precedente commento di spostare la sessione fuori dal tuo livello di business logic, a volte potresti doverlo fare comunque se stai lavorando con un codice legacy che è fortemente accoppiato alla sessione (il mio scenario).

Gli spazi dei nomi:

using System.Web; 
using System.IO; 
using System.Web.Hosting; 
using System.Web.SessionState; 

Il codice:

HttpWorkerRequest _wr = new SimpleWorkerRequest(
    "/dummyWorkerRequest", @"c:\inetpub\wwwroot\dummy", 
    "default.aspx", null, new StringWriter()); 

HttpContext.Current = new HttpContext(_wr); 

var sessionContainer = new HttpSessionStateContainer(
    "id", new SessionStateItemCollection(), 
    new HttpStaticObjectsCollection(), 10, true, 
    HttpCookieMode.AutoDetect, SessionStateMode.InProc, false); 

SessionStateUtility.AddHttpSessionStateToContext(
    HttpContext.Current, sessionContainer); 

È quindi possibile fare riferimento alla sessione senza ottenere un errore NullReferenceException:

HttpContext.Current.Session.Add("mySessionKey", 1); 

Questa è una combinazione di codice Ho compilato gli articoli seguenti:

+0

eccellente, grazie. –

+0

Grazie, buon lavoro – Manish

+0

Ricevo l'eccezione ViewEngine quando si chiama il metodo indice dalla classe di test dell'unità. C'è qualche soluzione per lo stesso? – Manish

Problemi correlati