2013-05-27 14 views
17

weiß, dass ich den Unterschied zwischen HttpContext und HttpContextWrapper unten ist ...Unterschied zwischen Httpcontext und HttpContextWrapper in Bezug auf den Unit-Tests und in Bezug auf Web Forms und MVC

Httpcontext

Dies ist der Jahrgang asp .net Kontext. Das Problem dabei ist, dass es keine Basisklasse hat und nicht virtuell ist und daher für das Testen unbrauchbar ist (kann es nicht vortäuschen). Es wird empfohlen, sie nicht als Funktionsargumente zu übergeben, sondern Variablen des Typs HttpContextBase umzuleiten.

Httpcontextbase

Dies ist die (neu C# 3.5) Ersatz zu Httpcontext. Da es abstrakt ist, ist es jetzt mockbar. Die Idee ist, dass Ihre Funktionen, von denen erwartet wird, dass sie einen Kontext passieren, eine davon erwarten sollten. Es wird konkret durch HttpContextWrapper

HttpContextWrapper

Ebenfalls neu in C# 3.5 implementiert - das ist die konkrete Umsetzung von Httpcontextbase ist. Verwenden Sie den neuen Befehl HttpContextWrapper (HttpContext.Current), um eine solche auf einer normalen Webseite zu erstellen.

Die Idee ist, dass Sie alle Ihre Variablen und Funktionsparameter vom Typ HttpContextBase deklarieren und ein IOC-Framework verwenden, zB Castle Windsor, um es injiziert zu bekommen. Im normalen Code ist Castle das Äquivalent von 'new HttpContextWrapper (HttpContext.Current)' zu injizieren, während im Testcode ein Mock von HttpContextBase gegeben wird.

Aber ich weiß nicht über seine tatsächliche Verwendung. Ich habe gehört, dass es beim Komponententest im Vergleich zu Web Forms nützlich ist. aber wie ist es sinnvoll?


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

Antwort

18

Ich habe gehört, dass es in den Vergleich mit Web Forms in Unit Testing nützlich ist. aber wie ist es sinnvoll?

Lassen Sie uns ein Beispiel für eine ASP.NET MVC-Controller handeln, die ein Cookie auf die Antwort hinzufügt:

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

Beachten Sie die Response-Eigenschaft dort. Es ist ein HttpResponseBase. So können wir es in einem Unit-Test verspotten:

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

und jetzt konnten wir einen Komponententest schreiben:

// 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); 

Und da alle Mitglieder virtuell sind, könnten wir einen Mockframework nutzen, die uns vermeiden würde die müssen diese Scheinklassen für den Komponententest schreiben.Zum Beispiel mit NSubstitute hier ist, wie der Test aussehen könnte:

// 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); 

Lassen Sie uns nun ein Webformular nehmen:

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

In diesem Fall wird die Reaktions Eigenschaft der Beton HttpResponse ist. Du bist also kaputt. Einheitentest kann nicht isoliert werden.

+0

Bedeutet dies, dass NVC über Aktionsmethoden verfügt, die in Unit Test Project aufgerufen werden können, und auf der anderen Seite Web Forms keine Methoden haben, stattdessen Seitenladeereignisse haben. Kann also nicht direkt angerufen werden? –

+1

Nein, das bedeutet, dass die MVC-Controller bereits mit den abstrahierten Klassen (HttpContextBase, HttpResponseBase, HttpRequestBase, ...) arbeiten, während ein WebForm mit den konkreten Klassen arbeitet (HttpContext, HttpResponse, HttpRequest, ...). ASP.NET MVC ist in diesem Sinne so konzipiert, dass alle vom Framework bereitgestellten Eigenschaften und Member Abstraktionen und keine konkreten Klassen sind. –

+0

Ich habe die Metadaten von 'httpresponse' und' httpresponsebase' überprüft. Beide haben dieselbe Anzahl von Eigenschaften und Methoden. Also gibt es keinen Unterschied zwischen ihnen. Recht ? –

Verwandte Themen