0

我有一个InsertTitle在数据库中插入一本书的方法。关于此功能的两个测试用例是验证输入的 ISBN 有效和无效时系统的行为。

有效的 ISBN 与以下 regEx 模式匹配:string pattern = "[0-9]*[-| ][0-9]*[-| ][0-9]*[-| ][0-9]*";

我遇到的第一个问题是弄清楚 ISBN 检查应该发生在哪个类中以避免依赖关系。正如您将在代码片段中看到的那样,我尝试在TitleController.cs中执行此操作,但未能成功编写正确的工作代码。

标题控制器.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分支上返回什么,以便在创建 UI 并从视图调用控制器时,我将能够返回一条消息,指出 ISBN 无效?我找不到任何合适的回报IActionResult

MockGtlTitleRepository : IGtlTitle 存储库

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另外,这个逻辑应该进入MockGtlTitleRepository吗?

4

2 回答 2

1

您的代码可能看起来像这样。尽量避免使用 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);
}
于 2020-05-26T09:07:39.293 回答
1

这与上面的答案非常相似,并改进了返回的 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);
    }

}
于 2020-05-26T09:24:27.807 回答