You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单元测试调用IServiceProvider.GetRequiredService遇注册错误如何解决?

问题:单元测试Foo.Get()时抛出DI注册异常

现有类Foo通过构造函数注入IServiceProvider,其Get()方法依赖GetRequiredService获取实例。单元测试调用Get("a")时抛出System.InvalidOperationException,提示"No service for type 'MyType' has been registered"。限制条件:

  • 无法修改Foo类及Get()方法实现
  • 无法Mock框架扩展方法IServiceProvider.GetRequiredService

实现代码:

public class Foo
{
    private IServiceProvider _serviceProvider;

    public Foo(IServiceProvider serviceProvider, IOtherService s1, IOtherService2 s2){
       _serviceProvider = serviceProvider;
       //...mapping other dependencies here    
    }

    public IType Get (string type){
        switch (type){
        case "a": return (IType)_serviceProvider.GetRequiredService(typeof(MyType));
        //other cases here 
        //......
        }
    }
}

当前单元测试代码(使用NUnit、Autofac.Extras.Moq、Moq):

[Test]
public void MyTest()
{
  using var am = AutoMock.GetLoose();
  var foo= am.Create<Foo>();

  //DI Exception when calling this method
  //No service for type 'MyType' has been registered
  foo.Get("a");
  
 //Assert here
 //....
}

可行解决方案

方案1:通过Autofac.Extras.Moq注册所需服务

AutoMock基于Autofac容器实现,直接将MyType注册到容器中,让IServiceProvider能正常解析该类型:

[Test]
public void MyTest()
{
  using var am = AutoMock.GetLoose();
  
  // 将MyType注册到AutoMock的容器,关联到IType接口
  am.ContainerBuilder.RegisterType<MyType>().As<IType>();
  
  var foo = am.Create<Foo>();
  
  // 调用Get("a")可正常获取实例
  var result = foo.Get("a");
  
  // 验证返回实例类型符合预期
  Assert.IsInstanceOf<MyType>(result);
}

如果MyType自身有依赖,可通过AutoMock自动注入,或手动注册其依赖项。

方案2:手动实现Mock版IServiceProvider

若不想依赖Autofac容器,可自定义一个简单的IServiceProvider实现,模拟服务解析逻辑(GetRequiredService扩展方法最终会调用GetService):

public class MockServiceProvider : IServiceProvider
{
    private readonly Dictionary<Type, object> _services = new Dictionary<Type, object>();

    public void Register<T>(T instance)
    {
        _services[typeof(T)] = instance;
    }

    public object GetService(Type serviceType)
    {
        _services.TryGetValue(serviceType, out var instance);
        return instance;
    }
}

测试时使用该模拟类:

[Test]
public void MyTest()
{
  // 创建模拟服务提供者并注册MyType实例
  var mockServiceProvider = new MockServiceProvider();
  var myTypeInstance = new Mock<IType>().Object; // 可根据需求Mock MyType的行为
  mockServiceProvider.Register<MyType>(myTypeInstance);
  
  // 手动构造Foo实例,注入其他依赖的Mock对象
  var s1Mock = new Mock<IOtherService>();
  var s2Mock = new Mock<IOtherService2>();
  var foo = new Foo(mockServiceProvider, s1Mock.Object, s2Mock.Object);
  
  var result = foo.Get("a");
  
  Assert.IsInstanceOf<IType>(result);
  // 可额外验证MyType的行为逻辑
}

注意:GetRequiredService会检查GetService返回值是否为null,确保注册的服务实例不为null即可避免异常。

内容的提问来源于stack exchange,提问作者Nilmi Nawalage

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 06:23:23