模拟 ASP 网络核心 GetService<T>

Mocking ASP Net Core GetService<T>

在 ASP NET Core 5 中模拟依赖注入 GetService 方法需要帮助,最小起订量 - 4.16.1,Nunit 3

这是我的生产代码:

class SomeClass(){  
    IServiceProvider serviceProvider;
   
    public SomeClass(IServiceProvider serviceProvider){
        this.serviceProvider = serviceProvider; 
    }

    void MethodHello(UserType type) {
        var service =  serviceProvider.GetService<Func<UserType, UserTypeBase>>();
                
        Console.WriteLine(service(type).GetAge());
    }
}
    
public enum UserType {
    Male,
    Female
}

我的单元测试:

class SomeClassTest{

    Mock<UserTypeBase> mockMale = new();
    Mock<UserTypeBase> mockFemale = new();
    
    Mock<IServiceProvider> serviceProvider = new Mock<IServiceProvider>(MockBehavior.Loose);

    [SetUp] 
    public SetUp(){
    
        Func<UserType, UserTypeBase> func = (type) => {
            if (type == UserType.Male)
              return mockMale.Object;
            else return mockFemale.Object;
        };
        serviceProvider.Setup(x => x.GetService(typeof(Func<UserType, UserTypeBase>)))
                       .Returns(func);
        mockMale.SetUp(x => x.GetAge()).Returns(20);
        mockFemale .SetUp(x => x.GetAge()).Returns(50);
    }
    
    [Test]
    public void Test_MethodHello(){
       
        new SomeClass(serviceProvider.Object).MethodHello(UserType.Male);
    
    }
}

有了这个,最小起订量框架抛出异常: 'System.RuntimeType' 类型的对象无法转换为 UserType 类型。

我尝试过的事情:

serviceProvider.Setup(x => x.GetService<Func<UserType, UserTypeBase>())
    .Returns(func);

serviceProvider.Setup(x => x.GetService(It.IsAny<Func<UserType, UserTypeBase>>))
    .Returns(func);

似乎没有任何效果。

除了代码味道,我建议使用实际的 IServiceProvider 以避免必须安排行为

class SomeClassTest{

    Mock<UserTypeBase> mockMale = new();
    Mock<UserTypeBase> mockFemale = new();
    
    IServiceProvider serviceProvider;

    [SetUp] 
    public void SetUp(){
    
        mockMale.SetUp(x => x.GetAge()).Returns(20);
        mockFemale .SetUp(x => x.GetAge()).Returns(50);

        Func<UserType, UserTypeBase> func = (type) => {
            if (type == UserType.Male)
              return mockMale.Object;
            else return mockFemale.Object;
        };

        IServiceCollection services = new ServiceCollection();
        services.AddSingleton(func);

        serviceProvider = services.BuildServiceProvider();
        
    }
    
    [Test]
    public void Test_MethodHello(){
       
        new SomeClass(serviceProvider).MethodHello(UserType.Male);
    
    }
}