Как вставить в контроллер отрицательный тестовый случай? - PullRequest
0 голосов
/ 26 мая 2020

У меня есть метод InsertTitle, который вставляет книгу в базу данных. Два из тестовых примеров в отношении этой функции - проверить, как ведет себя система, когда введенный ISBN действителен, а когда он недействителен.

Действительный ISBN соответствует следующему шаблону regEx: string pattern = "[0-9]*[-| ][0-9]*[-| ][0-9]*[-| ][0-9]*";

Первая проблема, с которой я столкнулся, - это выяснить, в каком классе должна выполняться проверка ISBN, чтобы избежать зависимостей. Как вы увидите в фрагментах кода, я попытался сделать это в TitleController.cs , но безуспешно написал правильный рабочий код.

TitleController.cs

[Route("api/title")]
    [HttpPost()]
    public IActionResult InsertTitle([FromBody] GtlTitle gtlTitle)
    {
        string pattern = "[0-9]*[-| ][0-9]*[-| ][0-9]*[-| ][0-9]*";
        Match m = Regex.Match(gtlTitle.ISBN, pattern, RegexOptions.IgnoreCase);
        if (m.Success)
        {
            try
            {
                return Ok(_gtlTitleRepository.InsertTitle(gtlTitle));
            }
            catch (Exception e)
            {
                return BadRequest();
            }
        }
        else
            // return ??? 

    }

Здесь возникает вторая и основная проблема. Что мне следует вернуть в ветке else, чтобы, когда пользовательский интерфейс будет создан и контроллер будет вызываться из представления, я смогу вернуть сообщение о том, что ISBN недействителен? Я не смог найти надлежащего возврата для IActionResult.

MockGtlTitleRepository: IGtlTitle Repository

public GtlTitle InsertTitle([FromBody] GtlTitle gtlTitle)
    {

        using (var connection = new SqlConnection(_connection))
        {
            connection.Open();
            connection.Query<GtlTitle>(@"INSERT INTO GTL_TITLE (ISBN, VolumeName, TitleDescription, PublicationDate, AuthorID, PublisherID, TempID) 
                                                        OUTPUT INSERTED.ISBN, INSERTED.VolumeName 
                                                        VALUES (@ISBN, @VolumeName, @TitleDescription, @PublicationDate, @AuthorID, @PublisherID, @TempID)",
                                                       new
                                                       {
                                                           gtlTitle.ISBN,
                                                           gtlTitle.VolumeName,
                                                           gtlTitle.TitleDescription,
                                                           gtlTitle.PublicationDate,
                                                           gtlTitle.AuthorID,
                                                           gtlTitle.PublisherID,
                                                           gtlTitle.TempID
                                                       }).First();
            return gtlTitle;
        }
    }

Следовательно, что должен возвращать метод InsertTitle else филиал? Кроме того, должен ли этот logi c go вместо MockGtlTitleRepository ?

Ответы [ 2 ]

1 голос
/ 26 мая 2020

Это очень похоже на ответ выше с улучшением исправленного BadRequest. Кроме того, добавление try / catch - хорошая идея при работе с базой данных или внешними зависимостями. Вы также можете добавить регистратор и использовать его при обработке исключений.

[Route("api/title")]
[HttpPost()]
public IActionResult InsertTitle([FromBody] GtlTitle gtlTitle)
{
    string pattern = "[0-9]*[-| ][0-9]*[-| ][0-9]*[-| ][0-9]*";
    Match m = Regex.Match(gtlTitle?.ISBN, pattern, RegexOptions.IgnoreCase);
    if (!m.Success)
      return BadRequest($"Could not match ISBN: {gtlTitle?.ISBN}")
    try
    {
       var title = _gtlTitleRepository.InsertTitle(gtlTitle)
        return Ok(title);
    }
    catch (Exception ex){
       _logger.Error("Unhandled error occured", ex);
       return StatusCode((int)HttpStatusCode.InternalServerError, ex);
    }

}
1 голос
/ 26 мая 2020

Ваш код может выглядеть примерно так. Старайтесь избегать использования ключевого слова else, поскольку в нем почти нет необходимости и он делает ваш код длиннее, чем должен быть. Для этого используйте ранний возврат. Проверка совпадения в контроллере возможна, но может быть перенесена в какую-либо службу. В этом случае я бы не стал выбирать этот маршрут, так как это такая маленькая проверка. Я не понимаю, почему вызов репозитория имеет какие-либо причины для сбоя, старайтесь не оборачивать код ненужными блоками try / catch.

[Route("api/title")]
[HttpPost()]
public IActionResult InsertTitle([FromBody] GtlTitle gtlTitle)
{
    string pattern = "[0-9]*[-| ][0-9]*[-| ][0-9]*[-| ][0-9]*";
    Match m = Regex.Match(gtlTitle.ISBN, pattern, RegexOptions.IgnoreCase);
    if (!m.Success)
      return BadRequest("Could not match")
    var title = _gtlTitleRepository.InsertTitle(gtlTitle)
    return Ok(title);
}
...