Unit test failing because of sessions
-
16-06-2021 - |
سؤال
I have written Custom model binder for my MVC3 application. I desided to use the Custom model binder is because I am using Sessions and unit tests are failing because of them.
Now my problem is that About
action does not accept any parameter but it need to pass the values stored in cart to view without using Session. Because with session it will fail the unit test. Model binder only works if I pass the cart as parameter to About
.
Please suggest me if you have any ideas.
many Thanks
Model Binder
public class CartModelBinder : IModelBinder
{
private const string CartSessionKey = "Cart";
public object BindModel(ControllerContext controllerContext, ModelBindingContext modelBindingContext)
{
Cart cart = null;
if(IsCartExistInSession(controllerContext))
{
cart = GetCartFromSession(controllerContext);
}
else
{
cart = new Cart();
AddCartToSession(controllerContext, cart);
}
return cart;
}
private static Cart GetCartFromSession(ControllerContext controllerContext)
{
return controllerContext.HttpContext.Session[CartSessionKey] as Cart;
}
private static void AddCartToSession(ControllerContext controllerContext, Cart cart)
{
controllerContext.HttpContext.Session[CartSessionKey] = cart;
}
private static bool IsCartExistInSession(ControllerContext controllerContext)
{
return controllerContext.HttpContext.Session[CartSessionKey] != null;
}
}
Controller
[HttpPost]
public ActionResult AddToCartfromAbout(Cart cart, int productId = 2)
{
var product = _productRepository.Products.First(p => p.ProductId == productId);
cart.AddItem(product, 1);
return View("About");
}
public ActionResult About()
{
// Need something here to get the value of cart
return View(cart);
}
المحلول
This Link may solve you problem. You need to download the source and DLLs from the link above and them you can assign the value to Session in Test.
[Test]
public void AddSessionStarShouldSaveFormToSession()
{
// Arrange
TestControllerBuilder builder = new TestControllerBuilder();
StarsController controller = new StarsController();
builder.InitializeController(controller);
controller.HttpContext.Session["NewStarName"] = "alpha c";
// Act
RedirectResult result = controller.Index() as RedirectResult;
// Assert
Assert.IsTrue(result.Url.Equals("Index"));
}
نصائح أخرى
I would suggest use Moq (or any other tool for mocking your data) and pass the values on the controller constructor. (Not sure, but mabe use Dependency Injection would help on this if it is not too much over-engineering)