Here is the scenario:
I'm writing a test for my controller and need to setup a view model titled CheckoutViewModel
. My controller method, Products
does not take CheckoutViewModel
as a parameter, so I cannot pass it in that way.
Currently, the test fails returning a Null Exception
because CheckoutViewModel
is not getting set and called.
Question: How can I setup my
CheckoutViewModel
with data.
Error Details:
System.NullReferenceException
Object reference not set to an instance of an object
Current Test
[TestMethod]
public void Products_ProductControllerIsCalled_ReturnsViewWithProducts()
{
// Arrange
var currentSession = _autoMoqer.GetMock<ICurrentSession>().Object;
ProductController productController = new ProductController(currentSession);
var checkoutViewModel = new CheckoutViewModel
{
CheckoutId = new Guid()
};
// Act
ActionResult result = productController.Products();
// Assert
Assert.IsInstanceOfType(result, typeof(ViewResult));
}
Controller
[AccectReadVerbs]
public ActionResult Products()
{
CheckoutViewModel checkoutViewModel = GetCheckoutViewModel();
var checkoutId = checkoutViewModel.CheckoutId;
var result = _productOrchestrator.Products(checkoutId, currentSession)
return View(result);
}
Failing on this method
private CheckoutViewModel GetCheckoutViewModel()
{
if(Session["CheckoutViewModel"] == null)
{
return new CheckoutViewModel();
}
return (CheckoutViewModel)Session["CheckoutViewModel"];
}
If GetCheckoutViewModel has some dependencies on ie services, dbConnection or other complex classes, you need to add a class with an interface, move the method for GetCheckOutViewModel to the class and take the new interface as a dependency to the controller. Then you need to mock the new interface.
Or edit your viewmodel to take interface dependencies on the stuff that stands in the way of unit testing, ie the Session.
I think you could create some interface:
public interface ISessionManager { Session session {get; set;} }
Then your controller constructor:
public ProductsController(ISessionManager sm) { _sessionManager = sm; }
Then you can pass a mocked instance to your controller.
I'm guessing that the exceptions is due to the fact that when you're running the unit test there will not be any (webserver) session available. What you want do is to isolate your tests from any external dependencies - and a session state that is part of the webserver hosting environment would be an external dependency.
To solve this you need to either mock or stub out the Session object from your test. There are many ways to do this, but the easiest way would be to make Session a public property on the Controller. From your test you would then set the Session to an instance you create within your test.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.