如何使用 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);
}
下面提到的是检查特定交易 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);
}