Moq IServiceProvider / IServiceScope

The general rule is that you don't mock types that you don't own. Unless you need to verify the calls made to the service provider, just build the IServiceProvider from a ServiceCollection in your tests.


As already stated, Moq does not allow setup of extension methods.

In this case however the source code of the said extension methods are available on Github

ServiceProviderServiceExtensions.

The usual way around an issue like this is to find out what the extension methods do and mock a path safely through it's execution.

The base type in all of this is the IServiceProvider and its object Getservice(Type type) method. This method is what is ultimately called when resolving the service type. And we are only dealing with abstraction (interfaces) then that makes using moq all the more easier.

//Arrange
var serviceProvider = new Mock<IServiceProvider>();
serviceProvider
    .Setup(x => x.GetService(typeof(ConfigurationDbContext)))
    .Returns(new ConfigurationDbContext(Options, StoreOptions));

var serviceScope = new Mock<IServiceScope>();
serviceScope.Setup(x => x.ServiceProvider).Returns(serviceProvider.Object);

var serviceScopeFactory = new Mock<IServiceScopeFactory>();
serviceScopeFactory
    .Setup(x => x.CreateScope())
    .Returns(serviceScope.Object);

serviceProvider
    .Setup(x => x.GetService(typeof(IServiceScopeFactory)))
    .Returns(serviceScopeFactory.Object);

var sut = new ApiResourceRepository(serviceProvider.Object);

//Act
var actual = sut.Get(myIntValue);

//Asssert
//...

Review the code above and you would see how the arrangement satisfies the expected behavior of the extension methods and by extension (no pun intended) the method under test.