【问题标题】:How to pass my DbContext object for testing using xunit and moq如何使用 xunit 和 moq 传递我的 DbContext 对象进行测试
【发布时间】:2020-11-03 22:32:50
【问题描述】:

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

        [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.

我是 moq 和 xunit 的新手。

请帮我解决这个问题。

提前致谢

【问题讨论】:

  • 在测试代码中,我使用的是内存数据库,并创建了与内存数据库链接的上下文,而不是使用真实数据库。

标签: .net-core moq xunit.net


【解决方案1】:

这里是初始化部分

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

【讨论】:

    【解决方案2】:

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

    你在这里做这个:

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

    GetRequiredService&lt;T&gt;是扩展IServiceProvider的扩展方法,可以看到here

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

    关于这个话题的进一步讨论存在here。该问题使用 MSTest 而不是 XUnit,但您的问题是特定于 Moq 的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-12
      • 1970-01-01
      • 1970-01-01
      • 2021-10-20
      • 2018-01-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多