Moq IServiceProvider / IServiceScope

前端 未结 5 1543
挽巷
挽巷 2021-02-01 14:01

I am trying to create a Mock (using Moq) for an IServiceProvider so that I can test my repository class:

public class ApiResourceRepository : IApiRe         


        
5条回答
  •  轻奢々
    轻奢々 (楼主)
    2021-02-01 14:41

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

提交回复
热议问题