如何在xUnit中使用泛型适当地模拟扩展方法? [英] How to properly mock extension methods with generics in xUnit?

查看:0
本文介绍了如何在xUnit中使用泛型适当地模拟扩展方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试模拟我的一项服务,以下是真正的代码:

public class PhaseService : IPhaseService
    {
        private readonly IRepository<Phase> _phaseRepository;
        private readonly IMapper _mapper;
        private readonly HrbContext _context;

        public PhaseService(IRepository<Phase> phaseRepository, IMapper mapper, HrbContext context)
        {
            _phaseRepository = phaseRepository;
            _mapper = mapper;
            _context = context;
        }

        public async Task<PhaseDto> GetAsync(Guid id)
        {
            var result = await _phaseRepository.GetActiveAsync(id);
            return _mapper.Map<PhaseDto>(result);
        }
}

它使用扩展方法,如下所示:

namespace HRB_Server.Application.Extensions
{
    public static class RepositoryExtensions
    {
        /// <summary>
        /// Returns the entity to which the given id is a match (no navigation properties loaded). Throws exceptions if the entity is not found or if is not active.
        /// </summary>
        public static async Task<T> GetActiveAsync<T>(this IRepository<T> repo, Guid id)
            where T : BaseEntity
        {
            T entity = await repo.GetAsync(id);

            if (entity == null)
            {
                throw new EntityNotFoundException(typeof(T), id);
            }

            if (!entity.IsActive)
            {
                throw new EntityNotActiveException(typeof(T), id);
            }

            return entity;
        }
}

这是我的xUnit测试:

namespace HRB_Server.Tests.Services
{
    public class PhaseServiceTest
    {
        private readonly Mock<IRepository<Phase>> _repository;
        private readonly Mock<IMapper> _mapper;
        private readonly Mock<HrbContext> _context;

        public PhaseServiceTest()
        {
            _repository = new Mock<IRepository<Phase>>();
            //_mapper = new Mock<IMapper>();
            _mapper = null;
            //_context = new Mock<HrbContext>(new DbContextOptions<HrbContext>(), new HttpContextAccessor());
            _context = null;
        }

        [Fact]
        public void GetPhase_ActivePhaseObject_PhaseShouldExist()
        {
            // Arrange
            var newGuid = Guid.NewGuid();
            var phase = GetSamplePhase(newGuid);

            _repository.Setup(x => RepositoryExtensions.GetActiveAsync<Phase>(_repository, It.IsAny<Guid>()))
                .Returns(GetSamplePhase(newGuid));

            var phaseService = new PhaseService(_repository.Object, _mapper.Object, _context.Object);

            // Act
            var result = phaseService.GetAsync(newGuid);

            // Assert (expected, actual)
            Assert.Equal(phase.Result.Id, newGuid);
        }
}

我收到的错误是在_存储库的设置中:

repository.Setup(x => RepositoryExtensions.GetActiveAsync<Phase>(_repository, It.IsAny<Guid>()))
                    .Returns(GetSamplePhase(newGuid));  

它说无法将模拟的存储库转换为真实的存储库,但我不应该在这里使用模拟的存储库吗?

我想要实现的是测试我的真实服务并模拟存储库,对吗?我在这里做得对吗?

推荐答案

假设您使用的是最大批量生产,请不要尝试模拟扩展方法。

因为您控制了扩展方法的代码,所以可以通过扩展方法模拟安全路径。

扩展在本例中使用GetAsync,假设它也不是扩展,则需要对其进行模拟。

//...

 _repository
    .Setup(x => x.GetAsync(It.IsAny<Guid>()))
    .ReturnsAsync(GetSamplePhase(newGuid));

//...

它将允许测试在执行时通过GetActiveAsync代码,如果失败,还会引发异常等,如代码中所述。

这篇关于如何在xUnit中使用泛型适当地模拟扩展方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆