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