2011-09-29 11 views
5

ho il seguente controller:come testare il codice di stato HTTP impostato un'azione ASP.NET MVC con MSpec

public sealed class SomeController : Controller 
{ 
    public ActionResult PageNotFound() 
    { 
     Response.StatusCode = 404; 

     return View("404"); 
    } 
} 

ho creato una specifica MSpec:

[Subject(typeof (SomeController))] 
public class when_invalid_page_is_requested : SomeControllerSpec 
{ 
    Because of =() => result = Controller.PageNotFound(); 

    It should_set_status_code_to_404 = 
     () => Controller.Response.StatusCode.ShouldEqual(404); 
} 

public abstract class SomeControllerSpec 
{ 
    protected static HomeController Controller; 

    Establish context =() => { Controller = new SomeController(); }; 
} 

Ma a causa di come Istanzio il controller, HttpContext è nullo. Quale sarebbe il modo migliore per testare il codice di stato impostato dall'azione PageNotFound?

EDIT: Inviato una risposta al di sotto

risposta

6

trovato un modo per farlo utilizzando Moq.

[Subject(typeof (SomeController))] 
public class when_invalid_page_is_requested : SomeControllerSpec 
{ 
    Because of =() => result = Controller.PageNotFound(); 

    It should_set_status_code_to_404 = 
     () => HttpResponse.VerifySet(hr => hr.StatusCode = 404); 
} 

public abstract class SomeControllerSpec 
{ 
    protected static SomeController Controller; 
    protected static Mock<ControllerContext> ControllerContext; 
    protected static Mock<HttpResponseBase> HttpResponse; 

    Establish context =() => 
    { 
     ControllerContext = new Mock<ControllerContext>(); 
     HttpResponse = new Mock<HttpResponseBase>(); 
     ControllerContext.SetupGet(cc => cc.HttpContext.Response) 
         .Returns(HttpResponse.Object); 

     Controller = new SomeController 
         { 
          ControllerContext = ControllerContext.Object 
         }; 
    }; 
} 

Non molto elegante. Se riesci a pensare a un modo migliore - fammi sapere.

3

È possibile utilizzare:

_controller.Response.StatusCode 
+0

Ho aggiornato la mia domanda con ulteriori informazioni. –

+0

Hai bisogno di deriderlo prima. Ad esempio chiamando 'controller.SetMockControllerContext()' da https://gist.github.com/johnnyreilly/4959924#file-mvcmockhelpers-cs. –

3

Un'altra opzione utilizzando MvcContrib 's TestControllerBuilder ...

var myController = new MyController(); 

var testControllerBuilder = new TestControllerBuilder(); 
testControllerBuilder.InitializeController(myController); 

e quindi utilizzando NUnit (direi la versione Moq avrebbe funzionato proprio come lo avete) ...

myController.Response.AssertWasCalled(response => response.StatusCode = 400); 

Tutto il brutto lavoro di setup e mocking è ancora in corso, ma da MvcContrib invece che all'interno del test. Ecco un post su using the TestControllerBuilder.