如何使用 xunit 和 moq 传递我的 DbContext 对象进行测试

How to pass my DbContext object for testing using xunit and moq

下面提到的是检查特定交易 ID 的详细信息是否存在的测试函数。

        [Fact]
        public async Task GetAllBlobDetails_Test()
        {
           _serviceScopeFactory.Setup(x => x.CreateScope().ServiceProvider.GetRequiredService<MriDbContext>()).Returns(_context);
           BlobStatusEntity blobStatusEntity =  await _bspRepository.GetBlobDetails("123");
           Assert.NotNull(blobStatusEntity)
        }

_serviceScopeFactory 在哪里

Mock<IServiceScopeFactory> _serviceScopeFactory = new Mock<IServiceScopeFactory>();
(Microsoft.Extensions.DependencyInjection)

在上面的函数中,它为特定的 transactionId ("123") 调用 _bspRepository.GetBlobDetails

这里是 GetBlobDetails 的定义

 public async Task<BlobStatusEntity> GetBlobDetails(string transactionId)
        {

                if (String.IsNullOrEmpty(transactionId))
                {
                    throw new ArgumentNullException(nameof(transactionId));
                }

                MriDbContext mriDbcontext = _scopeFactory.CreateScope().ServiceProvider.GetRequiredService<MriDbContext>();

                return await mriDbContext.BlobStatus.FirstOrDefaultAsync(ele => ele.TransactionId == transactionId);
        }

其中 _scopeFactory 是 IServiceScopeFactory _scopeFactory 从构造函数中注入的

当我运行上面的测试函数GetAllBlobDetails_Test时,我得到如下错误。

Message: 
    System.NotSupportedException : Unsupported expression: ... => ....GetRequiredService<MriDbContext>()
    Extension methods (here: ServiceProviderServiceExtensions.GetRequiredService) may not be used in setup / verification expressions.

我是最小起订量和 xunit 的新手。

请帮我解决这个问题。

提前致谢

所以这里的根本原因是您不能在 Moq 中模拟扩展方法

你在这里做的:

 _serviceScopeFactory.Setup(x => x.CreateScope().ServiceProvider.GetRequiredService<MriDbContext>()).Returns(_context);

GetRequiredService<T>是扩展IServiceProvider的扩展方法,可以看到here

根据您要测试的具体情况(您是测试上下文创建还是实际写入数据库?),您应该能够重新编写测试以避免模拟扩展方法并模拟正在使用的 public 实例方法。如果你真的想保留现有的结构,你甚至可以在 IServiceProvider 上模拟实际的实例方法。

存在关于此主题的进一步讨论 here。该问题使用 MSTest 而不是 XUnit,但您的问题是针对 Moq 的。

这里是初始化部分

  private BspRepository _bspRepository;
        private Mock<IServiceScopeFactory> _serviceScopeFactory;
        private Mock<ILogger<BspRepository>> _logger;
        private Mock<IMapper> _mapper;
        private DbContextOptions<MriDbContext> _options;
        private MriDbContext _context;
        private Mock<IServiceProvider> _serviceProvider;
        private Mock<IServiceScope> _serviceScope;
        public BSPRepositoryTests()
        {
            _serviceScopeFactory = new Mock<IServiceScopeFactory>();
            _logger = new Mock<ILogger<BspRepository>>();
            _mapper = new Mock<IMapper>();
            _serviceProvider = new Mock<IServiceProvider>();
            _serviceScope = new Mock<IServiceScope>();
            _options = SetupDBContext();
            _context = new MriDbContext(_options);
            _bspRepository = new BspRepository(_serviceScopeFactory.Object, _logger.Object, _mapper.Object);
            SetupData();
            SetupServices();

        }

我通过这种方式模拟对象解决了我的错误

 private void SetupServices()
        {
            _serviceProvider.Setup(x => x.GetService(typeof(MriDbContext))).Returns(_context);
            _serviceScope.Setup(x => x.ServiceProvider).Returns(_serviceProvider.Object);
            _serviceScopeFactory.Setup(x => x.CreateScope())
                .Returns(_serviceScope.Object);
        }