2013-05-27 17 views
17

conosco la differenza tra HttpContext e HttpContextWrapper è al di sotto ...Differenza tra HttpContext e HttpContextWrapper in termini di Unit Testing e in termini di Web Forms e MVC

HttpContext

Questa è l'epoca asp .net contesto. Il problema con questo è che non ha una classe base e non è virtuale, e quindi è inutilizzabile per il test (non può prenderlo in giro). Si consiglia di non passarlo in giro come argomenti di funzione, ma di passare le variabili di tipo HttpContextBase.

HttpContextBase

Questa è la (nuova per C# 3.5) la sostituzione di HttpContext. Dal momento che è astratto, ora è mockable. L'idea è che le tue funzioni che si aspettano di passare un contesto dovrebbero aspettarsi di ricevere uno di questi. E 'concretamente attuato da HttpContextWrapper

HttpContextWrapper

Un'altra novità di C# 3.5 - questa è l'attuazione concreta di HttpContextBase. Per crearne uno in una normale pagina Web, usa il nuovo HttpContextWrapper (HttpContext.Current).

L'idea è quella di rendere testabile il codice dell'unità, dichiarare che tutte le variabili e i parametri di funzione sono di tipo HttpContextBase e utilizzare un framework IOC, ad es. Castle Windsor per ottenerlo iniettato. Nel codice normale, il castello deve iniettare l'equivalente di "new HttpContextWrapper (HttpContext.Current)", mentre nel codice di test viene fornito un simulato di HttpContextBase.

Ma non sono a conoscenza del suo reale utilizzo. Ho sentito che è utile in Test unitario in confronto con Web Forms. ma come è utile?


I also know that we can use it to execute the controller and Action as mentioned here

risposta

18

Ho sentito che è utile in Unit Testing nel confronto con Web Forms. ma come è utile?

Facciamo un esempio di un'azione di controllo ASP.NET MVC, che è l'aggiunta di un cookie alla risposta:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     var cookie = new HttpCookie("foo", "bar"); 
     this.Response.Cookies.Add(cookie); 
     return View(); 
    } 
} 

Avviso di proprietà di risposta laggiù. È un HttpResponseBase. Così possiamo prendere in giro in una prova di unità:

public class HttpResponseMock: HttpResponseBase 
{ 
    private HttpCookieCollection cookies; 
    public override HttpCookieCollection Cookies 
    { 
     get 
     { 
      if (this.cookies == null) 
      { 
       this.cookies = new HttpCookieCollection(); 
      } 

      return this.cookies; 
     } 
    } 
} 

public class HttpContextMock: HttpContextBase 
{ 
    private HttpResponseBase response; 

    public override HttpResponseBase Response 
    { 
     get 
     { 
      if (this.response == null) 
      { 
       this.response = new HttpResponseMock(); 
      } 
      return this.response; 
     } 
    } 
} 

e ora possiamo scrivere uno unit test:

// arrange 
var sut = new HomeController(); 
var httpContext = new HttpContextMock(); 
sut.ControllerContext = new ControllerContext(httpContext, new RouteData(), sut); 

// act 
var actual = sut.Index(); 

// assert 
Assert.AreEqual("bar", sut.Response.Cookies["foo"].Value); 

E poiché tutti i membri sono virtuali potremmo usare un quadro di scherno che eviterebbe noi la è necessario scrivere quelle classi di simulazione per il test unitario.Ad esempio, con NSubstitute ecco come il test potrebbe essere:

// arrange 
var sut = new HomeController(); 
var context = Substitute.For<HttpContextBase>(); 
var response = Substitute.For<HttpResponseBase>(); 
var cookies = new HttpCookieCollection(); 
context.Response.Returns(response); 
context.Response.Cookies.Returns(cookies); 
sut.ControllerContext = new ControllerContext(context, new RouteData(), sut); 

// act 
var actual = sut.Index(); 

// assert 
Assert.AreEqual("bar", sut.Response.Cookies["foo"].Value); 

Ora diamo un WebForm:

protected void Page_Load(object sender, EventArgs) 
{ 
    var cookie = new HttpCookie("foo", "bar"); 
    this.Response.Cookies.Add(cookie); 
} 

In questo caso la proprietà Response è il calcestruzzo HttpResponse. Quindi sei stato beccato. Impossibile eseguire il test unitario separatamente.

+0

Significa che NVC ha metodi di azione che possono essere chiamati in Unit Test Project e che invece i moduli Web non hanno metodi, invece ha eventi di caricamento pagina. Quindi non può essere chiamato direttamente? –

+1

No, significa che i controller MVC funzionano già con le classi astratte (HttpContextBase, HttpResponseBase, HttpRequestBase, ...) mentre un Web Form funziona con le classi concrete (HttpContext, HttpResponse, HttpRequest, ...). ASP.NET MVC è progettato pensando a questo in modo che tutte le proprietà e i membri esposti dal framework siano astrazioni e non classi concrete. –

+0

Ho controllato i metadati di 'httpresponse' e' httpresponsebase'. Entrambi hanno lo stesso numero di proprietà e metodo. Quindi non c'è differenza tra loro. destra ? –

Problemi correlati