Search code examples
c#unit-testingasp.net-core-mvcnunit

Unit Test a Catch Block


How to unit test the below catch block?

Below is my controller definition:

public class RunController : Controller
{ 
    Public ActionResult GetExtraRun() 
    { 
        try{ 
             return View("ExtraRun"); 
        } catch(Exception ex) 
        { 
             _log.Error("Index -" + ex.Message, ex); 
             TempData[ErrorInfo] = GetErrorInfo(ex, "RunStatus"); 
             return RedirectToAction("Index", "RunErrorHandling"); 
        } 
     } 
} 

I am using NUnit and Moq latest with Asp.NET Core MVC 3.0 version.

So I will have two test case as below

  1. ) To check it is return View successfully.
  2. ) I need to check catch block as a part of code coverage.

So I need help in 2nd point in the above given code.


Solution

  • In order to test the desired block of code you would need to make the controller throw an exception when

    return View("ExtraRun"); 
    

    is invoked.

    This can be done by mocking the controller and overriding the View(string) function, which is virtual

    [Microsoft.AspNetCore.Mvc.NonAction]
    public virtual Microsoft.AspNetCore.Mvc.ViewResult View (string viewName);
    

    The following example used MOQ to mock the controller and override the intended function so that the controller behaved as expected when the test was exercised.

    //Arrange
    //...
    var mock = new Mock<RunController>({inject dependencies here});
    mock.CallBase = true;
    
    var exception = new Exception("Sample message");
    
    mock.Setup(_ => _.View(It.IsAny<string>())).Throws(exception);
    
    RunController controller = mock.Object;
    
    //Act
    var actual = controller.GetExtraRun() as RedirectToActionResult;
    
    //Assert
    actual.Should().NotBeNull(); //FluentAssertions
    
    //...perform desired assertions here
    

    Normally the subject under test is not mocked when unit testing. This case however required calling a member within the subject that needed to be configured to behave as desired. Which can be done by overriding it in a derived class. The same could have been done manually without the mocking framework but the framework simplifies the setup.