将依赖注入到 gRPC 服务中

3
我使用.NET Core在Visual Studio中使用Protobuff创建了一个gRPC服务,想要测试一下该服务。
该服务有一个构造函数:
public ConfigService(ILogger<ConfigService> logger)
{
    _logger = logger;
}

像ILogger一样,它被注入(我不知道如何注入),我想注入一个额外的参数 - 一个接口。这个接口应该可以在运行时轻松设置,因为我想在实际运行时设置特定的类,在测试时设置模拟类。例如:

public ConfigService(ILogger<ConfigService> logger, IMyInterface instance)
{
    _logger = logger;
    _myDepndency = instance;
}

在实际运行的情况下,对象将被创建为new RealClass(),但在测试时,可以轻松传递new MockClass()

启动类仍然是默认值:

 public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddGrpc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapGrpcService<ConfigService>();

            endpoints.MapGet("/", async context =>
            {
                await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
            });
        });
    }
}

我如何向服务的构造函数的第二个参数注入内容?


创建接口的实现或模拟,并将其传递给测试主体。 - Nkosi
展示测试并指出你遇到的问题所在。 - Nkosi
1个回答

8
在最简单的形式中,您只需在ConfigureServices方法中将依赖项添加到IServiceCollection即可;
public void ConfigureServices(IServiceCollection services)
{
    services.AddGrpc();
    services.AddScoped<IMyInterface, MyClassImplementingInterface>();
}

这将在服务集合中注册您的依赖项,并启用通过构造函数注入自动注入它。在您的测试中,您将自己注入它作为模拟对象,正如您所知道的那样。

有关更多信息,请参见此链接:ASP.NET Core 中的依赖注入


是的,就是这样。你也可以看一下模拟框架(例如moq:https://github.com/Moq/moq4/wiki/Quickstart),它将帮助你模拟依赖项。 - DaggeJ
我注意到每次gRPC端点接收请求时,MyClassImplementingInterface的构造函数都会运行。有没有办法使MyClassImplementingInterface只被实例化一次并重复使用?(对我来说,这意味着每次打开LMDB数据库...这应该只发生一次!)我的问题是...如何存储全局状态并从gRPC服务访问它,以便于昂贵的类库实例化? - AustEcon
1
编辑:算了。service.AddSingleton<IMyInterface,MyClassImplementingInterface>(); 对于我的用例来说已经足够了。 - AustEcon
@DaggeJ 或许有点晚了,注册完依赖项后,我该如何在grpc服务中获取它呢?在参考链接中,它展示了我们如何在Main()函数中获取它,即serviceScope.ServiceProvider.GetRequiredService<IMyDependency>()。但是我该如何在我的grpc服务类中获取它呢?假设我有一个gRPC类 public class GreeterService: GreeterServiceBase{ public override Task<SayHelloResponse> SayHlelo(SayHelloRequest request, ServerCallContext context) {...} }。 看起来我无法从上下文对象中获取IServiceCollection。 - kzfid
@DaggeJ 从未意识到这是由 DI 框架通过构造函数注入自动完成的。谢谢。 - kzfid
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接