C# 如何在控制器中插入否定测试用例?
我有一个方法C# 如何在控制器中插入否定测试用例?,c#,asp.net-core,asp.net-web-api,.net-core,dependency-injection,C#,Asp.net Core,Asp.net Web Api,.net Core,Dependency Injection,我有一个方法InsertTitle,可以在数据库中插入一本书。与此功能相关的两个测试用例用于验证输入的ISBN有效和无效时系统的行为 有效的ISBN与以下正则表达式模式匹配:string pattern=“[0-9]*[-[0-9]*[-[0-9]*[-[0-9]*[-[0-9]*” 我遇到的第一个问题是弄清楚应该在哪个类中进行ISBN检查以避免依赖关系。正如您将在代码片段中看到的,我曾在标题controller.cs中尝试过这样做,但没有成功地编写出正确的工作代码 标题控制器.cs [Rout
InsertTitle
,可以在数据库中插入一本书。与此功能相关的两个测试用例用于验证输入的ISBN有效和无效时系统的行为
有效的ISBN与以下正则表达式模式匹配:string pattern=“[0-9]*[-[0-9]*[-[0-9]*[-[0-9]*[-[0-9]*”代码>
我遇到的第一个问题是弄清楚应该在哪个类中进行ISBN检查以避免依赖关系。正如您将在代码片段中看到的,我曾在标题controller.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 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;
}
}
public gtltile InsertTitle([FromBody]gtltile gtltile)
{
使用(var连接=新的SqlConnection(_连接))
{
connection.Open();
connection.Query(@“插入GTL_标题(ISBN、VolumeName、TitleDescription、PublicationDate、AuthorID、PublisherID、TempID))
输出INSERTED.ISBN,INSERTED.VolumeName
值(@ISBN、@VolumeName、@TitleDescription、@PublicationDate、@AuthorID、@PublisherID、@TempID)”,
新的
{
gtlTitle.ISBN,
gtltle.VolumeName,
gtlTitle.标题说明,
gtltite.PublicationDate,
gtlTitle.AuthorID,
Gttitle.PublisherID,
gtltite.TempID
}).First();
返回gtltle;
}
}
因此,InsertTitle
方法在else
分支上应该返回什么?此外,是否应该将此逻辑放入MockGtlTitleRepository?您的代码可能类似于此。尽量避免使用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);
}
您的代码可能看起来像这样。尽量避免使用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);
}
这与上面的答案非常相似,但返回的错误请求有所改进。另外,在处理数据库或外部依赖项时,添加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);
}
}
这与上面的答案非常相似,但返回的错误请求有所改进。另外,在处理数据库或外部依赖项时,添加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);
}
}
您还可以将错误添加到特定属性的ModelState中,然后返回BadRequest(ModelState)。这将返回标准格式的响应。另一个选项是在模型中的ISBN属性上添加一个[Regex]
属性以自动验证它(尽管对于非API控制器,您确实需要在操作开始时手动检查模型状态是否有效),您还可以将错误添加到特定属性的ModelState中,然后返回BadRequest(ModelState)。这将返回标准格式的响应。另一个选项是在模型中的ISBN属性上添加一个[Regex]
属性,以自动验证它(尽管对于非API控制器,您确实需要在操作开始时手动检查模型状态是否有效)