2

Below mentioned is the test function that checks if details exist for the particular 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)
        }

where _serviceScopeFactory is

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

In the above function it calls _bspRepository.GetBlobDetails for particular transactionId ("123")

So here is the definition for 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);
        }

where _scopeFactory is IServiceScopeFactory _scopeFactory which is injected from the constructor.

When I am running the above test function GetAllBlobDetails_Test, I am getting the following error like this.

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

I am new to moq and xunit.

Please help me to resolve this issue.

Thanks in advance

istrupin
  • 1,423
  • 16
  • 32
akhil
  • 1,649
  • 3
  • 19
  • 31
  • In test code, I am using an in-memory database and I created my context which is linked to in-memory database instead of the using real database. – akhil Jul 14 '20 at 15:41

2 Answers2

3

So the root cause here is that you can't mock an extension method in Moq

You're doing this here:

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

GetRequiredService<T> is an extension method that extends IServiceProvider which you can see here

Depending on what the specific case you're trying to test is (are you testing the context creation, or the actual write to the DB?), you should be able to re-write your test to avoid mocking the extension method and mocking the public instance methods being used instead. You could even mock the actual instance method on IServiceProvider if you really wanted to keep the existing structure.

Further discussion of this topic exists here. That question uses MSTest rather than XUnit, but your issue here is specific to Moq.

istrupin
  • 1,423
  • 16
  • 32
2

Here is the initialization part

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

        }

I resolved my error by mocking objects in this way

 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);
        }
akhil
  • 1,649
  • 3
  • 19
  • 31