vista una pasar net mvc entre datos controladores controlador busqueda asp asp.net-mvc unit-testing

una - Controlador de prueba de la unidad ASP.NET MVC con HttpContext



search asp net core (5)

Estoy intentando escribir una prueba unitaria para mi controlador único para verificar si una vista se devolvió correctamente, pero este controlador tiene un controlador base que accede a HttpContext.Current.Session. Cada vez que creo una nueva instancia de mi controlador, se llama al constructor del controlador base y la prueba falla con una excepción de puntero nulo en HttpContext.Current.Session. Aquí está el código:

public class BaseController : Controller { protected BaseController() { ViewData["UserID"] = HttpContext.Current.Session["UserID"]; } } public class IndexController : BaseController { public ActionResult Index() { return View("Index.aspx"); } } [TestMethod] public void Retrieve_IndexTest() { // Arrange const string expectedViewName = "Index"; IndexController controller = new IndexController(); // Act var result = controller.Index() as ViewResult; // Assert Assert.IsNotNull(result, "Should have returned a ViewResult"); Assert.AreEqual(expectedViewName, result.ViewName, "View name should have been {0}", expectedViewName); }

¿Alguna idea sobre cómo simular (usando Moq) la sesión a la que se accede en el controlador base para que se ejecute la prueba en el controlador descendiente?


A menos que use Typemock o Moles, no puede .

En ASP.NET MVC no se supone que uses HttpContext.Current. Cambie su clase base para usar ControllerBase.ControllerContext : tiene una propiedad HttpContext que expone la clase HttpContextBase comprobable.

Aquí hay un ejemplo de cómo puede usar Moq para configurar un Mock HttpContextBase:

var httpCtxStub = new Mock<HttpContextBase>(); var controllerCtx = new ControllerContext(); controllerCtx.HttpContext = httpCtxStub.Object; sut.ControllerContext = controllerCtx; // Exercise and verify the sut

donde sut representa el sistema bajo prueba (SUT), es decir, el controlador que desea probar.



Probablemente deberías usar un ActionFilter lugar de una clase base para este tipo de cosas

[UserIdBind] public class IndexController : Controller { public ActionResult Index() { return View("Index.aspx"); } }


Retazo:

var request = new SimpleWorkerRequest("/dummy", @"c:/inetpub/wwwroot/dummy", "dummy.html", null, new StringWriter()); var context = new HttpContext(request); SessionStateUtility.AddHttpSessionStateToContext(context, new TestSession()); HttpContext.Current = context;

Implementación de TestSession ():

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.SessionState; namespace m1k4.Framework.Test { public class TestSession : IHttpSessionState { private Dictionary<string, object> state = new Dictionary<string, object>(); #region IHttpSessionState Members public void Abandon() { throw new NotImplementedException(); } public void Add(string name, object value) { this.state.Add(name, value); } public void Clear() { throw new NotImplementedException(); } public int CodePage { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } public System.Web.HttpCookieMode CookieMode { get { throw new NotImplementedException(); } } public void CopyTo(Array array, int index) { throw new NotImplementedException(); } public int Count { get { throw new NotImplementedException(); } } public System.Collections.IEnumerator GetEnumerator() { throw new NotImplementedException(); } public bool IsCookieless { get { throw new NotImplementedException(); } } public bool IsNewSession { get { throw new NotImplementedException(); } } public bool IsReadOnly { get { throw new NotImplementedException(); } } public bool IsSynchronized { get { throw new NotImplementedException(); } } public System.Collections.Specialized.NameObjectCollectionBase.KeysCollection Keys { get { throw new NotImplementedException(); } } public int LCID { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } public SessionStateMode Mode { get { throw new NotImplementedException(); } } public void Remove(string name) { this.state.Remove(name); } public void RemoveAll() { this.state = new Dictionary<string, object>(); } public void RemoveAt(int index) { throw new NotImplementedException(); } public string SessionID { get { return "Test Session"; } } public System.Web.HttpStaticObjectsCollection StaticObjects { get { throw new NotImplementedException(); } } public object SyncRoot { get { throw new NotImplementedException(); } } public int Timeout { get { return 10; } set { throw new NotImplementedException(); } } public object this[int index] { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } public object this[string name] { get { return this.state[name]; } set { this.state[name] = value; } } #endregion } }


Si está utilizando Typemock , puede hacer esto:

Isolate.WhenCalled(()=>controller.HttpContext.Current.Session["UserID"]) .WillReturn("your id");

El código de prueba se verá así:

[TestMethod] public void Retrieve_IndexTest() { // Arrange const string expectedViewName = "Index"; IndexController controller = new IndexController(); Isolate.WhenCalled(()=>controller.HttpContext.Current.Session["UserID"]) .WillReturn("your id"); // Act var result = controller.Index() as ViewResult; // Assert Assert.IsNotNull(result, "Should have returned a ViewResult"); Assert.AreEqual(expectedViewName, result.ViewName, "View name should have been {0}", expectedViewName); }