C# 返回IActionResult的单元测试控制器方法
我正在构建一个ASP.NET核心WebAPI,并试图为控制器编写单元测试。我发现的大多数示例都来自旧的WebAPI/WebAPI2平台,似乎与新的核心控制器没有关联 我的控制器方法正在返回C# 返回IActionResult的单元测试控制器方法,c#,unit-testing,asp.net-core,.net-core,asp.net-core-webapi,C#,Unit Testing,Asp.net Core,.net Core,Asp.net Core Webapi,我正在构建一个ASP.NET核心WebAPI,并试图为控制器编写单元测试。我发现的大多数示例都来自旧的WebAPI/WebAPI2平台,似乎与新的核心控制器没有关联 我的控制器方法正在返回IActionResults。但是,IActionResult对象只有一个需要控制器上下文的executesultasync()方法。我正在手动实例化控制器,因此此实例中的控制器上下文为null,这会在调用executesultasync时导致异常。从本质上讲,这将引导我走上一条非常艰难的道路,让这些单元测试成
IActionResults
。但是,IActionResult
对象只有一个需要控制器上下文的executesultasync()
方法。我正在手动实例化控制器,因此此实例中的控制器上下文为null,这会在调用executesultasync
时导致异常。从本质上讲,这将引导我走上一条非常艰难的道路,让这些单元测试成功完成,而且非常混乱。我一直在想,必须有一种更简单/正确的方法来测试API控制器
此外,如果这有什么不同,我的控制器也没有使用async/await
我试图实现的简单示例:
控制器方法:
[HttpGet(Name = "GetOrdersRoute")]
public IActionResult GetOrders([FromQuery]int page = 0)
{
try
{
var query = _repository.GetAll().ToList();
int totalCount = query.Count;
int totalPages = (int)Math.Ceiling((double)totalCount / pageSize) - 1;
var orders = query.Skip(pageSize * page).Take(pageSize);
return Ok(new
{
TotalCount = totalCount,
TotalPages = totalPages,
Orders = orders
});
}
catch (Exception ex)
{
return BadRequest(ex);
}
}
单元测试:
[Fact]
public void GetOrders_WithOrdersInRepo_ReturnsOk()
{
// arrange
var controller = new OrdersController(new MockRepository());
// act
IActionResult result = controller.GetOrders();
// assert
Assert.Equal(HttpStatusCode.OK, ????);
}
假设有点像
public IActionResult GetOrders() {
var orders = repository.All();
return Ok(orders);
}
本例中的控制器返回一个类
将结果强制转换为方法中返回的类型,并对该类型执行断言
[Fact]
public void GetOrders_WithOrdersInRepo_ReturnsOk() {
// arrange
var controller = new OrdersController(new MockRepository());
// act
var result = controller.GetOrders();
var okResult = result as OkObjectResult;
// assert
Assert.IsNotNull(okResult);
Assert.AreEqual(200, okResult.StatusCode);
}
你也可以做一些很酷的事情,比如:
var result = await controller.GetOrders();//
var okResult = result as ObjectResult;
// assert
Assert.NotNull(okResult);
Assert.True(okResult is OkObjectResult);
Assert.IsType<TheTypeYouAreExpecting>(okResult.Value);
Assert.Equal(StatusCodes.Status200OK, okResult.StatusCode);
var result=await controller.GetOrders()//
var okResult=作为ObjectResult的结果;
//断言
Assert.NotNull(okResult);
True(okResult是OkObjectResult);
IsType(okResult.Value);
Assert.Equal(StatusCodes.Status200OK、okResult.StatusCode);
谢谢您还可以使用ActionResult类作为控制器结果(假设您有类型订单)。 在这种情况下,您可以使用如下内容:
[ProducesResponseType(typeof(Orders), StatusCodes.Status200OK)]
public ActionResult<Orders> GetOrders()
{
return service.GetOrders();
}
[Fact]
public void GetOrders_WithOrdersInRepo_ReturnsOk() {
// arrange
var controller = new OrdersController(new MockRepository());
// act
var result = controller.GetOrders();
// assert
var okResult = Assert.IsType<OkObjectResult>(result);
Assert.IsNotNull(okResult);
Assert.AreEqual(200, okResult.StatusCode);
}
没有正确地映射它 建议强制转换到
ObjectResult
的其他答案,但只有当您返回OkObjectResult
\NotFoundObjectResult
\等时,它才起作用。但服务器可以返回从StatusCodeResult
派生的NotFound
\OkResult
例如:
public class SampleController : ControllerBase
{
public async Task<IActionResult> FooAsync(int? id)
{
if (id == 0)
{
// returned "NotFoundResult" base type "StatusCodeResult"
return NotFound();
}
if (id == 1)
{
// returned "StatusCodeResult" base type "StatusCodeResult"
return StatusCode(StatusCodes.Status415UnsupportedMediaType);
}
// returned "OkObjectResult" base type "ObjectResult"
return new OkObjectResult("some message");
}
}
这样做的一个好方法是:
[ProducesResponseType(typeof(Orders), StatusCodes.Status200OK)]
public ActionResult<Orders> GetOrders()
{
return service.GetOrders();
}
[Fact]
public void GetOrders_WithOrdersInRepo_ReturnsOk() {
// arrange
var controller = new OrdersController(new MockRepository());
// act
var result = controller.GetOrders();
// assert
var okResult = Assert.IsType<OkObjectResult>(result);
Assert.IsNotNull(okResult);
Assert.AreEqual(200, okResult.StatusCode);
}
[事实]
公共作废GetOrders\u with OrdersInRepo\u ReturnsOk(){
//安排
var controller=neworderscontroller(new MockRepository());
//表演
var result=controller.GetOrders();
//断言
var okResult=Assert.IsType(结果);
Assert.IsNotNull(okResult);
Assert.AreEqual(200,okResult.StatusCode);
}
公共异步任务调用扩展数据\u ReturnsHttpNotFound\u用于InvalidJobNum\u ReturnsStoredRxOrder()
{
var SCANICONTROLLER=新的SCANICONTROLLER(\u记录器,\u scanInService);
var okResult=等待扫描InControl.CallRxData(rxOrderRequest);
var notFoundResult=等待扫描InControl.CallRxData(invalidRxOrderRequest);
var okResultWithScanInCheckFalse=wait scanInController.CallRxData(rxOrderRequest);
var okResultWithEmptyAelAntiFakeDatas=等待扫描InControl.CallRxData(rxOrderRequest);
//断言
Assert.That(okResult,Is.TypeOf());
Assert.That(notFoundResult,Is.TypeOf());
Assert.IsFalse(((作为ObjectResult的okResultWithScanInCheckFalse)。作为RxOrder的值)。IsSecurity);`在此处输入代码`
}
显示GetOrders
方法。你用那种方法返回什么。将结果强制转换为您在方法中返回的类型,并对其执行断言。您好(Nkosi:)我是否可以将整个结果对象与预期对象进行比较,以便检查返回代码和对象?现在,Assert.AreEqual(实际、预期)似乎不起作用。编辑:对象是一个字符串。“我必须做出断言吗?”松鼠杀手说,那是因为它们是两个独立的实例。您可以从结果中提取对象,并在控制两者的情况下对其进行比较。@Squirrelkiller,例如Assert.AreEquan(myObject,okResult.Value)
wheremyObject
被假定为从模拟中返回并在控制器操作中传递给Ok()
的对象。当您仅返回Ok()时,会出现此问题没有内容,它正在重新调整OkResult而不是OkObjectResult。当强制转换到OkObjectResult时,它的状态代码不是总是200吗?
[Fact]
public void GetOrders_WithOrdersInRepo_ReturnsOk() {
// arrange
var controller = new OrdersController(new MockRepository());
// act
var result = controller.GetOrders();
// assert
var okResult = Assert.IsType<OkObjectResult>(result);
Assert.IsNotNull(okResult);
Assert.AreEqual(200, okResult.StatusCode);
}