Я создал относительно простой контроллер следующим образом:

[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");
            }

        }
...

Я новичок в модульном тестировании и изо всех сил пытаюсь заставить работать самые простые тесты. Я использую XUnit и Moq в Visual Studio 2017.

Чтобы окунуться в воду, я хотел проверить, что метод 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;
        }

Дайте мне знать, если вам нужны какие-либо детали репозитория или объекта. Я ожидаю, что проблема будет в моем неправильном понимании настройки фиктивных объектов, в любом случае я этого не вижу.

2
TDC 19 Янв 2018 в 18:42

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 для Microsoft.Extensions.DependencyInjection

1
Nkosi 19 Янв 2018 в 16:12