Вернуть BadRequest с нулевым обязательным свойством в модели .net core web api - PullRequest
0 голосов
/ 24 октября 2019

Итак, у меня есть контроллер с методом create:

[Authorize]
[Route("[controller]")]
[ApiController]
public class ConversionsController : ControllerBase
{
    private readonly IGenericService<Conversion> _conversionService;
    public ConversionsController(IGenericService<Conversion> conversionService) => _conversionService = conversionService;

    /// <summary>
    /// Creates a new conversion
    /// </summary>
    /// <param name="conversion">The conversion</param>
    /// <returns></returns>
    [HttpPost]
    [ProducesResponseType(typeof(Conversion), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> CreateAsync(ConversionViewModel conversion)
    {
        if (conversion == null) return BadRequest();
        if (!ModelState.IsValid) return BadRequest(ModelState);

        var request = ModelFactory.Create(conversion);

        _conversionService.Create(request);
        await _conversionService.SaveChangesAsync();

        return Created(nameof(Get), new Sxp.Web.ActionResult<Conversion>(request, string.Format(Resources.EntityCreated, "conversion")));
    }
}

Как вы можете видеть, если нет модели, она выдаст неверный запрос (который работает).

Но следующая строка с указанием if (!ModelState.IsValid) никогда не работает. Он всегда возвращает действительное значение даже с обязательным свойством null .

. Я написал тест, который всегда дает сбой:

[Test]
public async Task ReturnBadRequestIfNullRequiredProperty()
{
    // Assemble
    var services = ConversionsControllerContext.GivenServices();
    var controller = services.WhenCreateController();

    // Act
    var actionResult = await controller.CreateAsync(new ConversionViewModel());
    var badRequestResult = actionResult as BadRequestResult;

    // Assert
    badRequestResult.Should().NotBeNull();
    badRequestResult?.StatusCode.Should().Be(StatusCodes.Status400BadRequest);
}

Как вы можете видеть здесь, япросто передайте CategoryViewModel без каких-либо установленных свойств, но он потерпит неудачу.

Модель представления выглядит следующим образом:

public class ConversionViewModel
{
    public int Id { get; set; }
    [Range(1, int.MaxValue, ErrorMessageResourceName = "RangeErrorMessage", ErrorMessageResourceType = typeof(Resources))] public int FeedId { get; set; }
    [Required(ErrorMessageResourceName = "RequiredErrorMessage", ErrorMessageResourceType = typeof(Resources)), StringLength(100, ErrorMessageResourceName = "StringLengthErrorMessage", ErrorMessageResourceType = typeof(Resources))] public string Name { get; set; }
    [Required(ErrorMessageResourceName = "RequiredErrorMessage", ErrorMessageResourceType = typeof(Resources)), StringLength(100, ErrorMessageResourceName = "StringLengthErrorMessage", ErrorMessageResourceType = typeof(Resources))] public string FieldName { get; set; }
    [Required(ErrorMessageResourceName = "RequiredErrorMessage", ErrorMessageResourceType = typeof(Resources)), StringLength(100, ErrorMessageResourceName = "StringLengthErrorMessage", ErrorMessageResourceType = typeof(Resources))] public string Expression { get; set; }
    public double Value { get; set; }
    public MathOperator MathOperator { get; set; }
    public FilterOperator FilterOperator { get; set; }
}

Единственное, о чем я могу думать, это то, что яотключена автоматическая проверка состояния:

.ConfigureApiBehaviorOptions(options => { options.SuppressModelStateInvalidFilter = true; });

Что, как мне казалось, позволило мне справиться с этим в контроллере.

Кто-нибудь сталкивался с этим раньше?

Ответы [ 2 ]

1 голос
/ 24 октября 2019

Вы запускаете модульное тестирование, а не сквозное интеграционное тестирование, поэтому существуют определенные проблемы с инфраструктурой, которые не выполняются при выполнении теста.

Эти атрибуты аннотации данных являются метаданными, которые распознаются толькокаркас во время выполнения, а не во время изолированного модульного теста, поскольку он фактически читается компоновщиком модели во время работы приложения.

Если предполагалось, что каркас подтвердит модель, тогда необходим интеграционный тест.

Ссылка Интеграционные тесты в ASP.NET Core

В противном случае тестируемому объекту (контроллеру) необходимо обновить ModelState вручную при организации теста, чтобычто при работе он ведет себя так, как ожидалось.

Недопустимое состояние модели проверяется путем добавления ошибок, используя AddModelError, как показано в тесте ниже:

[Test]
public async Task ReturnBadRequestIfNullRequiredProperty() {
    // Arrange / Assemble
    var services = ConversionsControllerContext.GivenServices();
    var controller = services.WhenCreateController();
    controller.ModelState.AddModelError("Name","Name required"); //<-- Invalidate model state
    //...other desired errors.

    // Act
    var actionResult = await controller.CreateAsync(new ConversionViewModel());
    var badRequestResult = actionResult as BadRequestResult;

    // Assert
    badRequestResult.Should().NotBeNull();
    badRequestResult?.StatusCode.Should().Be(StatusCodes.Status400BadRequest);
}

Ссылка Тестовый контроллерлогика в ASP.NET Core

0 голосов
/ 24 октября 2019

Если вы используете services.AddMvcCore вместо services.AddMvc, тогда добавьте

services.AddDataAnnotations();

в метод Startup.ConfigureServices

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...