Moq IServiceProvider / IServiceScope

前端 未结 5 1555
挽巷
挽巷 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:38

    I'd like to argue that when you need to add that much ceremony just to mock a simple method, then maybe your code isn't very testable. So another option would be to hide the service locator behind a more test and mock friendly interface (and in my opinion a nicer one too):

    public interface IServiceLocator : IDisposable
    {
        T Get();
    }
    
    public class ScopedServiceLocator : IServiceLocator
    {
        private readonly IServiceScopeFactory _factory;
        private IServiceScope _scope;
    
        public ScopedServiceLocator(IServiceScopeFactory factory)
        {
            _factory = factory;
        }
    
        public T Get()
        {
            if (_scope == null)
                _scope = _factory.CreateScope();
    
            return _scope.ServiceProvider.GetService();
        }
    
    
        public void Dispose()
        {
            _scope?.Dispose();
            _scope = null;
        }
    }
    

    I've only implemented the GetService method here, but you could easily add/remove so that the locator better suites your need. And an example of how to use it;

    public class ALongRunningTask : IRunForALongTime
    {
        private readonly IServiceLocator _serviceLocator;
    
        public ALongRunningTask(IServiceLocator serviceLocator)
        {
            _serviceLocator = serviceLocator;
        }
    
        public void Run()
        {
            using (_serviceLocator)
            {
                var repository = _serviceLocator.Get();
            }
        }
    }
    

提交回复
热议问题