public ViewResult Add() { return View("Add", new StuffViewModel()); } [HttpPost] public ActionResult Add(StuffViewModel stuffViewModel) { if (ModelState.IsValid) { Stuff stuff = mappingService.Map<StuffViewModel, Stuff>(stuffViewModel); stuffRepository.InsertOrUpdate(stuff); return RedirectToAction("List"); } return View("Add", stuffViewModel); }As you can see both actions use same view. The first action is for displaying the view (HTTP GET) and the other is for handling submission from the view (HTTP POST).
Then below are the unit tests to cover both actions functionalities:
public class Add { private Mock<IStuffRepository> stuffRepository; private Mock<IMappingService> mappingService; private StuffsController controller; public Add() { stuffRepository = new Mock<IStuffRepository>(); mappingService = new Mock<IMappingService>(); controller = new StuffsController(stuffRepository.Object, mappingService.Object); } [Fact] public void GET_should_return_add_view() { // Arrange // Act var result = controller.Add(); // Assert var viewResult = Assert.IsType<ViewResult>(result); Assert.Equal("Add", viewResult.ViewName); } [Fact] public void GET_should_have_StuffViewModels() { // Arrange // Act var result = controller.Add(); // Assert //Assert.IsAssignableFrom<StuffViewModel>(result.ViewData.Model); Assert.IsType<StuffViewModel>(result.ViewData.Model); } [Fact] public void POST_should_save_to_database_if_model_is_valid() { // Arrange StuffViewModel stuffViewModel = new StuffViewModel { StuffID = 1 }; Stuff stuff = new Stuff { StuffID = 1}; mappingService.Setup(m => m.Map<StuffViewModel, Stuff>(It.IsAny<StuffViewModel>())) .Returns(stuff); // Act controller.Add(stuffViewModel); //Assert stuffRepository.Verify(o => o.InsertOrUpdate(stuff), Times.Once()); } [Fact] public void POST_should_redirect_to_list_view_after_saving() { // Arrange StuffViewModel stuffViewModel = new StuffViewModel { StuffID = 1 }; Stuff stuff = new Stuff { StuffID = 1 }; mappingService.Setup(m => m.Map<StuffViewModel, Stuff>(It.IsAny<StuffViewModel>())) .Returns(stuff); // Act var result = controller.Add(stuffViewModel); // Assert var redirectToRouteResult = Assert.IsAssignableFrom<RedirectToRouteResult>(result); Assert.Equal("List", redirectToRouteResult.RouteValues["action"]); } [Fact] public void POST_if_not_valid_should_not_save_into_database() { // Arrange StuffViewModel stuffViewModel = new StuffViewModel { StuffID = 1 }; Stuff stuff = new Stuff { StuffID = 1 }; mappingService.Setup(m => m.Map<StuffViewModel, Stuff>(It.IsAny<StuffViewModel>())) .Returns(stuff); controller.ModelState.AddModelError("key", "error"); // Act var result = controller.Add(stuffViewModel); // Assert stuffRepository.Verify(o => o.InsertOrUpdate(stuff), Times.Never()); } [Fact] public void POST_if_not_valid_should_return_to_add_view() { // Arrange StuffViewModel stuffViewModel = new StuffViewModel { StuffID = 1 }; Stuff stuff = new Stuff { StuffID = 1 }; mappingService.Setup(m => m.Map<StuffViewModel, Stuff>(It.IsAny<StuffViewModel>())) .Returns(stuff); controller.ModelState.AddModelError("key", "error"); // Act var result = controller.Add(stuffViewModel); // Assert var viewResult = Assert.IsType<ViewResult>(result); Assert.Equal("Add", viewResult.ViewName); } [Fact] public void POST_if_not_valid_should_return_view_with_StuffViewModel() { // Arrange StuffViewModel stuffViewModel = new StuffViewModel { StuffID = 1 }; Stuff stuff = new Stuff { StuffID = 1 }; mappingService.Setup(m => m.Map<StuffViewModel, Stuff>(It.IsAny<StuffViewModel>())) .Returns(stuff); controller.ModelState.AddModelError("key", "error"); // Act var result = controller.Add(stuffViewModel); // Assert var viewResult = Assert.IsType<ViewResult>(result); Assert.IsType<StuffViewModel>(viewResult.ViewData.Model); } }