1

I have implemented a ViewFactory to seperate the generation of View Models from the Controller logic. The ViewFactory implementation has a comprenhensive set of unit tests that cover all paths.

As this is a refactor of existing code, I had unit tests which cover the same scenarios, with similar mock setups at the controller level.

Now that I have moved the code to the View Factory, both sets of unit tests still work, however, I now have duplication of test logic and from a maintenance point of view, this certainly does not feel right. Other factors might suggest that this is also not a good practice.

I am looking to cut down the number of tests in the controller but I am struggling what I should be looking to cover. Put simply, I would have a single mock of the ViewFactory and the view returned in the ActionResult would be this, so no real value (in my opinion). However, not having any tests also does not sit well with me.

I do plan to implement changes to other view models that will expose properties based on validation that will change how the view itself presents the data, so the ViewFactory would generate a model with DuplicateIdFound property and the view would then display an error. For these models, I would look to test the scenarios as the value of these properties would drive ModelState errors.

Is the simple test below enough, knowing that ViewFactory tests cover the rest?

/// <summary>
/// GET PaymentDetails
/// </summary>
[TestMethod]
public void PaymentDetailsGet()
{
    _mockViewFactory.Setup(x => x.CreateView<PaymentDetailsViewModel, PaymentDetailsViewModel>(It.IsAny<PaymentDetailsViewModel>()))
        .Returns(new PaymentDetailsViewModel());

    var controller = new AccountController(null, _mockPrincipalLoader.Object, _mockUserEntityService.Object, _mockPaymentService.Object, _mockPlanEntityService.Object, _mockBillingService.Object, _mockAlertsService.Object, _mockViewFactory.Object, _mockResetEntityService.Object, _mockMonitorEntityService.Object);

    controller.ControllerContext = new ControllerContext(Helpers.CreateRequestContext(true), controller);

    var result = (ViewResult)controller.PaymentDetails(Guid.NewGuid());
    Assert.IsNotNull(result);

    var message = controller.TempData["message"];
    Assert.IsNull(message);

    var model = result.Model as PaymentDetailsViewModel;
    Assert.IsNotNull(model);
}

Please note that in the context of this Controller method, only the ViewFactory is used, the others are to be refactored;

[CustomAuthorize]
[HttpGet]
[CustomHttps]
public ActionResult PaymentDetails(Guid id)
{
    //Get View from Factory
    var viewModel = _viewFactory.CreateView<PaymentDetailsViewModel, PaymentDetailsViewModel>(new PaymentDetailsViewModel
    {
        UserId = CurrentUser.Id,
        Reference = id
    });

    return View(viewModel);
}
3

In your controller, you need to test the collaboration with ViewFactory. You're doing that correctly by mocking ViewFactory in your simple test, but you must also consider other test cases:

  • ViewFactory returns null
  • ViewFactory throws an exception

You should be able to configure your mock to throw an exception or return null. You should test that your controller either handles these edge cases or bubbles the appropriate exception.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.