I am trying to create a Mock (using Moq) for an IServiceProvider
so that I can test my repository class:
public class ApiResourceRepository : IApiRe
I was also looking for this, but i only needed to mock GetService. I always use AutoFac to auto generate mocks. In this example 'GetService' always returns a mocked instance. You can change the mock behavior afterwards with the freeze method.
Example:
Class to test:
public class ApiResourceRepository : ApiResourceRepository {
private readonly IServiceProvider _serviceProvider;
public ApiResourceRepository(IServiceProvider serviceProvider) {
_serviceProvider = serviceProvider;
}
public object Get(int id) {
using (var serviceScope = _serviceProvider.CreateScope()) {
var repo = serviceScope.ServiceProvider.GetService();
return repo.GetById(id);
}
}
}
Unit Test:
[Fact]
public void Test() {
// arrange
var fixture = new Fixture()
.Customize(new AutoMoqCustomization())
.Customize(new ServiceProviderCustomization());
fixture.Freeze>()
.Setup(m => m.GetById(It.IsAny()))
.Returns(new Person(Name = "John"));
// Act
var apiResource = _fixture.Create();
var person = apiResource.Get(1);
// Assert
...
}
Custom AutoFac provider
public class ServiceProviderCustomization : ICustomization {
public void Customize(IFixture fixture) {
var serviceProviderMock = fixture.Freeze>();
// GetService
serviceProviderMock
.Setup(m => m.GetService(It.IsAny()))
.Returns((Type type) => {
var mockType = typeof(Mock<>).MakeGenericType(type);
var mock = fixture.Create(mockType, new SpecimenContext(fixture)) as Mock;
// Inject mock again, so the behavior can be changed with _fixture.Freeze()
MethodInfo method = typeof(FixtureRegistrar).GetMethod("Inject");
MethodInfo genericMethod = method.MakeGenericMethod(mockType);
genericMethod.Invoke(null, new object[] { fixture, mock });
return mock.Object;
});
// Scoped
var serviceScopeMock = fixture.Freeze>();
serviceProviderMock
.As()
.Setup(m => m.CreateScope())
.Returns(serviceScopeMock.Object);
serviceProviderMock.As()
.Setup(m => m.GetRequiredService(typeof(IServiceScopeFactory)))
.Returns(serviceProviderMock.Object);
}
}