Search code examples
asp.net-web-apiodatamoqexceptionhandler

How to throw and get the exception object in MoQ WebAPI


I have an OData enabled WebAPI that contains

  1. TestController: It contains a single custom action method.
  2. WebApiExceptionHandler: Custom exception handler in WebApi, registered in WebApiConfig.cs.
  3. ITestManager: Interface
  4. TestManager: Class implementing the ITestManager. This class handles all the business logic for data. WebAPI controller TestController has a single function that calls this class.

    Also, there is a TestWebAPI Project which uses MoQ framework for testing. The TestMethod "Test_UpdatePackageVendorOnException__Success" uses MoQ setup to throw Exception in UpdateTestQuantity method. But when I debug this test method, when the exception is thrown, the debugger does not point in the WebApiExceptionHandler class. Ideally all exceptions occurring in the API are handled in the WebApiExceptionHandler class

The problem I am facing is that in my test method, I want to test something on the exception object returned by the WebApiExceptionHandler. But since the control is never going in the WebApiExceptionHandler, so I can't do that.

How can I modify the code so that in the TestMethod I can test the custom object returned by the WebApiExceptionHandler.

WebAPI Code:

    public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Services.Replace(typeof(IExceptionHandler), new WebApiExceptionHandler());

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        config.Routes.MapHttpRoute(
          name: "DefaultApiGetParam",
          routeTemplate: "api/{controller}/{key}/{count}",
          defaults: new { key = RouteParameter.Optional, count = RouteParameter.Optional }
        );
    }
}

public class WebApiExceptionHandler : ExceptionHandler
{
    public WebApiExceptionHandler()
    {
    }
    public override void Handle(ExceptionHandlerContext context)
    {
        try
        {
            var objCustomException = new CustomException(context.Exception);
            context.Result = new ResponseMessageResult(context.Request.CreateResponse(HttpStatusCode.InternalServerError, objCustomException);
        }
        catch (Exception)
        {
            base.Handle(context);
        }
    }

    public override bool ShouldHandle(ExceptionHandlerContext context)
    {
        return true;
    }
}


public interface ITestManager
{
    bool UpdateTestQuantity();

}

public class TestManager : ITestManager
{
    public TestManager()
    {
    }


    public bool UpdateTestQuantity()
    {
        //Custom Logic
        return true;
    }
}

public class TestController : ODataController
{
    ITestManager testManager;

    public TestController()
    {
        testManager = new TestManager();
    }

    public TestController(ITestManager iTestManager)
    {
        testManager = iTestManager;
    }

    public IHttpActionResult UpdateTestQuantity(ODataActionParameters param)
    {
        bool result = testManager.UpdateTestQuantity();
        return Ok();
    }
}

WebApiTest Project

[TestClass]
public class TestControllerTest
{

    Mock<ITestManager> iTestManagerMock;
    TestController objTestController;

    [TestInitialize]
    public void Setup()
    {
        iTestManagerMock = new Mock<ITestManager>();
    }

    [TestMethod]
    [ExpectedException(typeof(Exception), AllowDerivedTypes = true)]
    public void Test_UpdateTestQuantityOnException__Success()
    {
        iTestManagerMock.Setup(i => i.UpdateTestQuantity().Throws(new Exception());
        objTestController = new TestController(iTestManagerMock.Object);
        var objODataActionParameters = new ODataActionParameters();
        objTestController.Request = new HttpRequestMessage();
        objTestController.Configuration = new HttpConfiguration();
        IHttpActionResult objIHttpActionResult = objTestController.UpdateTestQuantity(objODataActionParameters);

        //Problem Area
        //Control never reaches here after the exception is thrown  
        //Want to check some property of exception object returned via Exception WebApiExceptionHandler 
    }

    [TestCleanup]
    public void Clean()
    {
        iTestManagerMock = null;
    }
}

Solution

  • Remove the [ExpectedException] test method attribute (which violates the AAA principle) and rewrite the assert section of your test to use the Assert.Throws NUnit method.