ASP.Net Web API控制器单元测试失败

时间:2018-01-19 15:42:11

标签: c# unit-testing moq xunit asp.net-core-webapi

我创建了一个相对简单的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方法,如果有一些区域,会返回一个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;
        }

如果您需要任何存储库或实体详细信息,请与我们联系。我期待这个问题出现在我对设置模拟对象的误解中,无论哪种方式我都看不到它。

1 个答案:

答案 0 :(得分:1)

调试并检查实际返回的类型。然后你可以看看你是否在检查错误的类型。可能会抛出错误并返回错误请求。

另一种确保在测试中的方法

// 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