ASP.Net Web API 控制器单元测试失败
ASP.Net Web API Controller Unit Test Fails
我自己创建了一个比较简单的Controller如下:
[Route("api/areas")]
public class AreasController : Controller
{
private IAreaRepository _areaRepository;
private ILogger<AreasController> _logger;
// Constructor.
public AreasController(
IAreaRepository areaRepository,
ILogger<AreasController> logger
)
{
_areaRepository = areaRepository;
_logger = logger;
}
[HttpGet()]
public IActionResult GetAreas()
{
try
{
_logger.LogTrace("AreasController.GetAreas called.");
// Create an IEnumerable of Area objects by calling the repository.
var areasFromRepo = _areaRepository.GetAreas();
var areas = Mapper.Map<IEnumerable<AreaDto>>(areasFromRepo);
// Return a code 200 'OK' along with an IEnumerable of AreaDto objects mapped from the Area entities.
return Ok(areas);
}
catch (Exception ex)
{
_logger.LogError($"Failed to get all Areas: {ex}");
return BadRequest("Error Occurred");
}
}
...
我是单元测试的新手,正在努力让最基本的测试工作。我在 Visual Studio 2017 年使用 XUnit 和 Moq。
为了让我的脚趾浸入水中,我想测试控制器上的 GetAreas 方法,如果有一些区域,return 一个 okObjectResult,但它没有!
这是我的测试:
[Fact]
public void ReturnAreasForGetAreas()
{
//Arrange
var area = new Area
{
Id = new Guid("761317f6-f9d7-4fa4-a8fe-c6179daee3da"),
Description = "Test Area",
SortIndex = 1
};
var _mockAreaRepository = new Mock<IAreaRepository>();
_mockAreaRepository
.Setup(x => x.GetAreas())
.Returns(new List<Area> { area });
var _mockLogger = new Mock<ILogger<AreasController>>();
var _sut = new AreasController(_mockAreaRepository.Object, _mockLogger.Object);
// Act
var result = _sut.GetAreas();
Assert.NotNull(result);
// Assert
var okResult = result.Should().BeOfType<OkObjectResult>().Subject;
}
如果您需要任何存储库或实体详细信息,请告诉我。我希望问题出在我对设置模拟对象的误解上,无论哪种方式我都看不到它。
调试并检查实际是什么类型return。然后你可以看看你是否在检查错误的类型。可能会抛出错误并且正在 returned 错误请求。
另一种方式保证在测试中
// Act
var result = _sut.GetAreas() as OkObjectResult;
//Assert
Assert.NotNull(result);
如果使用 Automapper,那么我还建议将 IMapper
注入控制器,以便在测试时也能够模拟它,以避免仅为测试而设置它。与静态依赖关系的紧密耦合会对代码的可测试性产生不良影响。
[Route("api/areas")]
public class AreasController : Controller {
private IAreaRepository _areaRepository;
private ILogger<AreasController> _logger;
private IMapper mapper;
// Constructor.
public AreasController(
IAreaRepository areaRepository,
ILogger<AreasController> logger,
IMapper mapper
) {
_areaRepository = areaRepository;
_logger = logger;
this.mapper = mapper;
}
[HttpGet()]
public IActionResult GetAreas() {
try {
_logger.LogTrace("AreasController.GetAreas called.");
// Create an IEnumerable of Area objects by calling the repository.
var areasFromRepo = _areaRepository.GetAreas();
var areas = mapper.Map<IEnumerable<AreaDto>>(areasFromRepo);
// Return a code 200 'OK' along with an IEnumerable of AreaDto objects mapped from the Area entities.
return Ok(areas);
} catch (Exception ex) {
_logger.LogError($"Failed to get all Areas: {ex}");
return BadRequest("Error Occurred");
}
}
//...
}
只需确保将抽象与其在组合根的实现相关联。
services.AddAutoMapper(assembly1, assembly2 /*, ...*/);
引用AutoMapper extensions for Microsoft.Extensions.DependencyInjection
我自己创建了一个比较简单的Controller如下:
[Route("api/areas")]
public class AreasController : Controller
{
private IAreaRepository _areaRepository;
private ILogger<AreasController> _logger;
// Constructor.
public AreasController(
IAreaRepository areaRepository,
ILogger<AreasController> logger
)
{
_areaRepository = areaRepository;
_logger = logger;
}
[HttpGet()]
public IActionResult GetAreas()
{
try
{
_logger.LogTrace("AreasController.GetAreas called.");
// Create an IEnumerable of Area objects by calling the repository.
var areasFromRepo = _areaRepository.GetAreas();
var areas = Mapper.Map<IEnumerable<AreaDto>>(areasFromRepo);
// Return a code 200 'OK' along with an IEnumerable of AreaDto objects mapped from the Area entities.
return Ok(areas);
}
catch (Exception ex)
{
_logger.LogError($"Failed to get all Areas: {ex}");
return BadRequest("Error Occurred");
}
}
...
我是单元测试的新手,正在努力让最基本的测试工作。我在 Visual Studio 2017 年使用 XUnit 和 Moq。
为了让我的脚趾浸入水中,我想测试控制器上的 GetAreas 方法,如果有一些区域,return 一个 okObjectResult,但它没有!
这是我的测试:
[Fact]
public void ReturnAreasForGetAreas()
{
//Arrange
var area = new Area
{
Id = new Guid("761317f6-f9d7-4fa4-a8fe-c6179daee3da"),
Description = "Test Area",
SortIndex = 1
};
var _mockAreaRepository = new Mock<IAreaRepository>();
_mockAreaRepository
.Setup(x => x.GetAreas())
.Returns(new List<Area> { area });
var _mockLogger = new Mock<ILogger<AreasController>>();
var _sut = new AreasController(_mockAreaRepository.Object, _mockLogger.Object);
// Act
var result = _sut.GetAreas();
Assert.NotNull(result);
// Assert
var okResult = result.Should().BeOfType<OkObjectResult>().Subject;
}
如果您需要任何存储库或实体详细信息,请告诉我。我希望问题出在我对设置模拟对象的误解上,无论哪种方式我都看不到它。
调试并检查实际是什么类型return。然后你可以看看你是否在检查错误的类型。可能会抛出错误并且正在 returned 错误请求。
另一种方式保证在测试中
// Act
var result = _sut.GetAreas() as OkObjectResult;
//Assert
Assert.NotNull(result);
如果使用 Automapper,那么我还建议将 IMapper
注入控制器,以便在测试时也能够模拟它,以避免仅为测试而设置它。与静态依赖关系的紧密耦合会对代码的可测试性产生不良影响。
[Route("api/areas")]
public class AreasController : Controller {
private IAreaRepository _areaRepository;
private ILogger<AreasController> _logger;
private IMapper mapper;
// Constructor.
public AreasController(
IAreaRepository areaRepository,
ILogger<AreasController> logger,
IMapper mapper
) {
_areaRepository = areaRepository;
_logger = logger;
this.mapper = mapper;
}
[HttpGet()]
public IActionResult GetAreas() {
try {
_logger.LogTrace("AreasController.GetAreas called.");
// Create an IEnumerable of Area objects by calling the repository.
var areasFromRepo = _areaRepository.GetAreas();
var areas = mapper.Map<IEnumerable<AreaDto>>(areasFromRepo);
// Return a code 200 'OK' along with an IEnumerable of AreaDto objects mapped from the Area entities.
return Ok(areas);
} catch (Exception ex) {
_logger.LogError($"Failed to get all Areas: {ex}");
return BadRequest("Error Occurred");
}
}
//...
}
只需确保将抽象与其在组合根的实现相关联。
services.AddAutoMapper(assembly1, assembly2 /*, ...*/);
引用AutoMapper extensions for Microsoft.Extensions.DependencyInjection