ASP. NET Основной модульный тест выдает исключение Null при тестировании ответа о проблеме контроллера - PullRequest
1 голос
/ 14 июля 2020

Я создаю базовые c модульные тесты для своего проекта. По какой-то причине я продолжаю получать исключение NullReferenceException при тестировании, когда я получаю ответ ControllerBase.Problem(String, String, Nullable<Int32>, String, String). Я уверен, что проблема заключается в несоответствии с контроллером, который на самом деле не работает, поскольку он, кажется, ведет себя отлично, когда контроллер работает.

Контроллер:

        [HttpGet("{id}")]
        [Produces("application/json")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        public IActionResult GetPatient([GuidNotEmpty] Guid id)
        {
            Patient patient = null;

            patient = _patientDbService.FindPatient(id);
            if (patient == null) {
                return Problem("Patient not found.", string.Empty, StatusCodes.Status404NotFound,
                    "An error occurred.", "https://tools.ietf.org/html/rfc7231#section-6.5.1");
            }

            return Ok(patient);
        }

Тест:

        [Fact]
        public void TestGetPatientFromIdPatientNotFound()

        {
            // Act
            IActionResult result = _patientController.GetPatient(Guid.NewGuid());

            // Assert
            Assert.IsType<ObjectResult>(result);
            Assert.NotNull(((ObjectResult)result).Value);
            Assert.IsType<ProblemDetails>(((ObjectResult)result).Value);
            Assert.Equal(((ObjectResult)result).StatusCode, StatusCodes.Status404NotFound);
        }

Результат:

X PatientServiceTest.PatientServiceUnitTest.TestGetPatientFromIdPatientNotFound [1ms]
Error Message:
   System.NullReferenceException : Object reference not set to an instance of an object.
Stack Trace:
   at Microsoft.AspNetCore.Mvc.ControllerBase.Problem(String detail, String instance, Nullable`1 statusCode, String title, String type)
   at PatientService.Controllers.PatientController.GetPatient(Guid id) in /home/surafel/coding/microservices-dev/c#/PatientService/Controllers/PatientController.cs:line 43
   at PatientServiceTest.PatientServiceUnitTest.TestGetPatientFromIdPatientNotFound() in /home/surafel/coding/microservices-dev/c#/PatientServiceTest/PatientServiceUnitTest.cs:line 69

1 Ответ

1 голос
/ 15 июля 2020

Как указал Алуан Хаддад в комментариях, этот Problem() вызывает ProblemDetailsFactory для создания ProblemDetails объектов, которые предоставляются менеджером служб. Диспетчер служб работает только тогда, когда приложение запущено: https://github.com/dotnet/aspnetcore/blob/master/src/Mvc/Mvc.Core/src/ControllerBase.cs#L194

Переменная ControllerBase.ProblemDetailsFactory может быть установлена, поэтому я создал макет ProblemDetailsFactory и установил фабрику контроллеров на экземпляр моего макета. Кажется, это заставляет его работать.

Mock:

    public class MockProblemDetailsFactory : ProblemDetailsFactory
    {
        public MockProblemDetailsFactory()
        {
        }

        public override ProblemDetails CreateProblemDetails(HttpContext httpContext,
            int? statusCode = default, string title = default,
            string type = default, string detail = default, string instance = default)
        {
            return new ProblemDetails() {
                Detail = detail,
                Instance = instance,
                Status = statusCode,
                Title = title,
                Type = type,
            };
        }

        public override ValidationProblemDetails CreateValidationProblemDetails(HttpContext httpContext,
            ModelStateDictionary modelStateDictionary, int? statusCode = default,
            string title = default, string type = default, string detail = default,
            string instance = default)
        {
            return new ValidationProblemDetails(new Dictionary<string, string[]>()) {
                Detail = detail,
                Instance = instance,
                Status = statusCode,
                Title = title,
                Type = type,
            };
        }
    }

Я добавил эту строку в настройку для этого модульного теста, и она решает проблему.

_patientController.ProblemDetailsFactory = new MockProblemDetailsFactory();
...