如何解决如何编写ASP.NET Core Web API控制器的单元测试
所以我对编写测试非常陌生。我创建了ASP.NET核心Web API和angular。我必须为Web API控制器编写单元测试。我一直在阅读有关如何开始使用ASP.NET Web API的单元测试的Microsoft文档。但是我仍然不确定如何编写适当的测试。
我的控制器代码
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class OrdersController : ControllerBase
{
private readonly IOrderRepository _repo;
private readonly IMapper _mapper;
public OrdersController(IOrderRepository repo,IMapper mapper)
{
_repo = repo;
_mapper = mapper;
}
[AllowAnonymous]
[HttpPost()]
public async Task<IActionResult> AddOrder(OrderForMappingDto orderForMappingDto)
{
//if(orderForMappingDto.ARentalOrNot == null)
//{
// throw new Exception("Value can't be left null");
//}
var orderToCreate = _mapper.Map<TblOrder>(orderForMappingDto);
var createdOrder = await _repo.AddOrder(orderToCreate);
return Ok(createdOrder);
}
}
我的存储库代码
public class OrderRepository : IOrderRepository
{
private readonly MovieRentalDBContext _context;
public OrderRepository(MovieRentalDBContext context)
{
_context = context;
}
public async Task<TblOrder> AddOrder(TblOrder tblOrder)
{
await _context.TblOrder.AddAsync(tblOrder);
await _context.SaveChangesAsync();
return tblOrder;
}
}
我知道有很多模拟可以做。但是我是否也需要模拟实体框架? 我写了一个简单的测试文件。
public void PostsAorder_WhenCalled_ReturnsOkWithResponse()
{
var mockOrderRepository = new Mock<IOrderRepository>();
var mockOrderMapper = new Mock<IMapper>();
var orderControllerObject = new OrdersController(mockOrderRepository.Object,mockOrderMapper.Object);
Task<IActionResult> contentResult = orderControllerObject.AddOrder(new OrderForMappingDto
{
ACustomerId = 3,AMovieId = 18,ARentalOrNot = false,AOrderedDate = DateTime.Now
}) ;
//var contentResult = actionResult as OkNegotiatedContentResult<OrderForMappingDto>;
Assert.IsNotNull(contentResult);
Assert.IsNotNull(contentResult.Result);
}
OkNegotioatedContent函数不适用于Tasks。我该如何将其用于任务。另外,即使我不提供最后3个参数(即使在DTO中它们被归类为[Required]
),测试仍通过。有人可以提供有关如何正确修改测试的帮助。
映射器配置-
解决方法
您的测试几乎可以。首先是固定版本,然后是一些解释:
[Fact]
public async Task GivenAValidOrder_WhenICallTheAsOrder_ThenItReturnsOkWithResponse()
{
//Arrange
var mockOrderMapper = new Mock<IMapper>();
mockOrderMapper.Setup(mapper => mapper.Map<TblOrder>(It.IsAny<OrderForMappingDto>()))
.Returns(new TblOrder());
var mockOrderRepository = new Mock<IOrderRepository>();
mockOrderRepository.Setup(repo => repo.AddOrder(It.IsAny<TblOrder>()))
.ReturnsAsync((TblOrder order) => order);
var SUT = new OrdersController(mockOrderRepository.Object,mockOrderMapper.Object);
//Act
var contentResult = await SUT.AddOrder(new OrderForMappingDto
{
ACustomerId = 3,AMovieId = 18,ARentalOrNot = false,AOrderedDate = DateTime.Now
});
//Assert
Assert.NotNull(contentResult);
Assert.IsAssignableFrom<OkObjectResult>(contentResult);
var result = ((OkObjectResult)contentResult).Value;
Assert.NotNull(result);
Assert.IsAssignableFrom<TblOrder>(result);
}
- 测试的名称遵循“何时提供” 结构,以便于理解在什么情况下控制器的行为应如何表现。
- 该测试现在是异步的,因为我们需要
await
完成控制器的操作以检查其结果。 - 我在代码中添加了
Arrange Act Assert
注释,以强调哪个阶段从何时开始。 - 我已将映射器模拟设置为返回新的
TblOrder
,并且将repo模拟设置为返回其收到的任何内容。 - 我将
orderControllerObject
重命名为SUT
,因为它强调了正在检查哪个组件(被测系统)。 - 在结果验证中,我使用了
IsAssingableForm
而不是IsType
,因为它还会检查派生类。在这种特殊情况下,这不是强制性的,但这是一个好习惯。 - 结果类型将为
OkObjectResult
而不是OkNegotiatedContentResult
,因此您应进行检查。 - 最后,我添加了额外的检查,以确保返回的对象的类型与预期的一样。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。