Как выбросить и получить объект исключения в MoQ WebAPI

У меня есть WebAPI с поддержкой OData, который содержит

  1. TestController: он содержит единственный метод настраиваемого действия.
  2. WebApiExceptionHandler: пользовательский обработчик исключений в WebApi, зарегистрированный в WebApiConfig.cs.
  3. ITestManager: Интерфейс
  4. TestManager: класс, реализующий ITestManager. Этот класс обрабатывает всю бизнес-логику данных. Контроллер WebAPI TestController имеет единственную функцию, которая вызывает этот класс.

    Также существует проект TestWebAPI, в котором для тестирования используется среда MoQ. TestMethod «Test_UpdatePackageVendorOnException__Success» использует настройку MoQ для создания исключения в методе UpdateTestQuantity. Но когда я отлаживаю этот тестовый метод, когда возникает исключение, отладчик не указывает на класс WebApiExceptionHandler. В идеале все исключения, возникающие в API, обрабатываются в классе WebApiExceptionHandler.

Проблема, с которой я столкнулся, заключается в том, что в моем методе тестирования я хочу что-то протестировать на объекте исключения, возвращаемом WebApiExceptionHandler. Но поскольку элемент управления никогда не попадает в WebApiExceptionHandler, я не могу этого сделать.

Как мне изменить код, чтобы в TestMethod я мог протестировать настраиваемый объект, возвращаемый WebApiExceptionHandler.

Код WebAPI:

    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

[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;
    }
}

person Quest    schedule 03.03.2017    source источник
comment
Есть способ получить много ненужной информации. Прочтите Как создать минимальный, полный и проверяемый пример.   -  person Serhii Shushliapin    schedule 03.03.2017
comment
Для этого потребуется интеграционный тест, в котором настроены все движущиеся части, а не модульный тест, подобный тому, который вы сейчас пытаетесь реализовать.   -  person Nkosi    schedule 03.03.2017
comment
@SergeyShushlyapin Плохо, что я предоставил много информации. Ваша точка зрения должным образом принята к сведению.   -  person Quest    schedule 06.03.2017
comment
@Nkosi, как я могу затем выполнить модульное тестирование ExceptionHandler в WebAPI.   -  person Quest    schedule 06.03.2017


Ответы (1)


Удалите атрибут [ExpectedException] метода тестирования (который нарушает принцип AAA) и перепишите assert < / em> вашего теста, чтобы использовать метод Assert.Throws NUnit.

person Serhii Shushliapin    schedule 03.03.2017
comment
Использование NUnit работает как шарм. Но у меня все еще есть одна проблема. Мне трудно понять тот факт, что я использовал ExceptionHandler для обработки всех исключений в API. Когда я использую MoQ iTestManagerMock.Setup (i = ›i.UpdateTestQuantity (). Throws (new Exception ()); для явного создания исключения, то почему элемент управления никогда не достигает класса ExceptionHandler, который возвращает объект Exception. В моем методе Test Мне нужно увидеть этот объект, возвращенный ExceptionHandler, чтобы выполнить Assert. - person Quest; 06.03.2017