web-dev-qa-db-fra.com

Automapper dans les tests xUnit et .NET Core 2.0

J'ai un projet .NET Core 2.0 qui contient un modèle de référentiel et des tests xUnit.

Maintenant, voici une partie de son code.

Contrôleur:

public class SchedulesController : Controller
{
    private readonly IScheduleRepository repository;
    private readonly IMapper mapper;

    public SchedulesController(IScheduleRepository repository, IMapper mapper)
    {
        this.repository = repository;
        this.mapper = mapper;
    }

    [HttpGet]
    public IActionResult Get()
    {
        var result = mapper.Map<IEnumerable<Schedule>, IEnumerable<ScheduleDto>>(source: repository.items);
        return new OkObjectResult(result);
    }
}

Ma classe de test:

public class SchedulesControllerTests
{
    [Fact]
    public void CanGet()
    {
        try
        {
            //Arrange
            Mock<IScheduleRepository> mockRepo = new Mock<IScheduleRepository>();
            mockRepo.Setup(m => m.items).Returns(new Schedule[]
            {
                new Schedule() { Id=1, Title = "Schedule1" },
                new Schedule() { Id=2, Title = "Schedule2" },
                new Schedule() { Id=3, Title = "Schedule3" }
            });

            var mockMapper = new Mock<IMapper>();
            mockMapper.Setup(x => x.Map<Schedule>(It.IsAny<ScheduleDto>()))
                .Returns((ScheduleDto source) => new Schedule() { Title = source.Title });

            SchedulesController controller = new SchedulesController(repository: mockRepo.Object, mapper: mockMapper.Object);

            //Act
            var result = controller.Get();

            //Assert
            var okResult = result as OkObjectResult;
            Assert.NotNull(okResult);

            var model = okResult.Value as IEnumerable<ScheduleDto>;
            Assert.NotNull(model);

        }
        catch (Exception ex)
        {
            //Assert
            Assert.False(false, ex.Message);
        }
    }
}

Problème auquel je suis confronté.

Mon problème est que lorsque j'exécute ce code avec un contexte de base de données et que j'exécute la méthode Get(), cela fonctionne bien, cela me donne tous les résultats.

Mais lorsque j'essaie d'exécuter le scénario de test, il ne renvoie aucune donnée de l'objet Dto. Quand j'ai débogué, j'ai trouvé que

  1. J'obtiens mon objet de test dans le contrôleur en utilisant mockRepo.

  2. Mais il semble que le mappeur automatique ne soit pas initialisé correctement, car lors du mappage, il ne renvoie rien dans

    var result = mapper.Map<IEnumerable<Schedule>, IEnumerable<ScheduleDto>>(source: repository.items);

Ce que j'ai essayé jusqu'à présent?

J'ai suivi toutes ces réponses mais ça ne marche toujours pas.

Mocking Mapper.Map () dans les tests unitaires

Comment simuler une transformation de liste à l'aide d'AutoMapper

Donc, j'ai besoin de l'aide de quelqu'un qui est bon dans xUnit et automapper, et j'ai besoin de conseils sur la façon d'initialiser correctement le mappeur simulé.

10
Bharat

Enfin, cela a fonctionné pour moi, j'ai suivi cette voie Comment écrire un test xUnit pour le service .net core 2.0 qui utilise AutoMapper et l'injection de dépendance?

Ici, je poste ma réponse et ma classe de test, si nécessaire, d'autres SO peuvent utiliser.

public class SchedulesControllerTests
{
    [Fact]
    public void CanGet()
    {
        try
        {
            //Arrange
            //Repository
            Mock<IScheduleRepository> mockRepo = new Mock<IScheduleRepository>();
            var schedules = new List<Schedule>(){
                new Schedule() { Id=1, Title = "Schedule1" },
                new Schedule() { Id=2, Title = "Schedule2" },
                new Schedule() { Id=3, Title = "Schedule3" }
            };

            mockRepo.Setup(m => m.items).Returns(value: schedules);

            //auto mapper configuration
            var mockMapper = new MapperConfiguration(cfg =>
            {
                cfg.AddProfile(new AutoMapperProfile());
            });
            var mapper = mockMapper.CreateMapper();

            SchedulesController controller = new SchedulesController(repository: mockRepo.Object, mapper: mapper);

            //Act
            var result = controller.Get();

            //Assert
            var okResult = result as OkObjectResult;
            if (okResult != null)
                Assert.NotNull(okResult);

            var model = okResult.Value as IEnumerable<ScheduleDto>;
            if (model.Count() > 0)
            {
                Assert.NotNull(model);

                var expected = model?.FirstOrDefault().Title;
                var actual = schedules?.FirstOrDefault().Title;

                Assert.Equal(expected: expected, actual: actual);
            }
        }
        catch (Exception ex)
        {
            //Assert
            Assert.False(false, ex.Message);
        }
    }
}
21
Bharat

J'avais besoin d'injecter IMapper, d'utiliser ProjectTo pour obtenir un IQueryable mappé, puis d'implémenter un peu plus de logique sur la requête après la carte. Voici donc ce que j'ai fait pour me moquer:

var models = new object[]
{
    ⋮
}.AsQueryable();
var mapper = new Mock<IMapper>();
mapper.Setup(x => x.ProjectTo(
        It.IsAny<IQueryable>(),
        It.IsAny<object>(),
        It.IsAny<Expression<Func<object, object>>[]>()))
    .Returns(models);
0
crgolden