简体   繁体   English

使用 DI 模拟调用.Net Core class 库

[英]Mock call to .Net Core class library with DI

I'm having trouble creating a console program to call the enrol method in referenced class library.我无法创建一个控制台程序来调用引用的 class 库中的注册方法。 I cannot get the dependencies injected except the config.除了配置之外,我无法注入依赖项。

The Class library contains the code to call: Class 库包含要调用的代码:

public interface IMyClient
{
    Task DoSomething(Request request);
}

public class MyClient : IMyClient
{
    private readonly MyClientConfig _config;
    private readonly ILogger<MClient> _logger;
    private readonly HttpClient _client;

    public MyClient()
    {

    }

    public MyClient(MyClientConfig config, ILogger<MyClient> logger, HttpClient client)
    {
        _config = config;
        _logger = logger;
        _client = client;
    }

    public async Task DoSomething(Request request)
    {
        // BREAKPOINT HERE HAS config (id = 1) but logger & client are null
    }
}

And the console program和控制台程序

class Program
{
    private static IServiceProvider _serviceProvider;
    static void Main(string[] args)
    {
        RegisterServices();
        IServiceScope scope = _serviceProvider.CreateScope();

        var request = new Request()
        {
            Id = 1
        };

        scope.ServiceProvider.GetRequiredService<IMyClient>().DoSomething(request);

        DisposeServices();
    }

    private static void RegisterServices()
    {
        var myClientConfig = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json", true, true)
            .Build().GetSection("MyClient").Get<MyClientConfig>();


        var services = new ServiceCollection();
        services.AddSingleton<IMyClient, MyClient>();
        services.AddSingleton<IMyClientConfig>(myClientConfig);
        _serviceProvider = services.BuildServiceProvider(true);
    }

    private static void DisposeServices()
    {
        if (_serviceProvider == null)
        {
            return;
        }
        if (_serviceProvider is IDisposable)
        {
            ((IDisposable)_serviceProvider).Dispose();
        }
    }
}

I tried adding in我尝试添加

services.AddSingleton<HttpClient>(new HttpClient());

to get the HttpCLient injected but to no avail.获取 HttpCLient 注入但无济于事。

Any help appreciated or advice on testing the call to DoSomething in the referenced project任何有关在引用项目中测试对 DoSomething 的调用的帮助或建议

You're not configuring your Logger and HttpClient in services .您没有在services中配置LoggerHttpClient You are also likely missing an additional Nuget package, Microsoft.Extensions.Logging.Console - install that if it's missing, since you mentioned this is a Console App您还可能缺少一个额外的 Nuget package, Microsoft.Extensions.Logging.Console - 如果它丢失,请安装它,因为您提到这是一个控制台应用程序

Modify your code as follows:修改您的代码如下:

    private static void RegisterServices()
    {

        var myClientConfig = new ConfigurationBuilder()
                                .AddJsonFile("appsettings.json", true, true)
                                .Build().GetSection("MyClient").Get<MyClientConfig>();

        var services = new ServiceCollection();
        services.AddSingleton<IMyClient, MyClient>();

        // Configure logging service
        services.AddLogging(cfg => cfg.AddConsole())
                .AddTransient<MyClient>();

        // Configure HttpClient - might need some constructor params, depending on your use case
        services.AddSingleton<HttpClient>(new HttpClient());

        _serviceProvider = services.BuildServiceProvider(true);
    }

Also, very important : remove your empty constructor in MyClient !另外,非常重要:删除MyClient中的空构造函数 You never want that one hit, In fact, it's far better for the program to crash in debugging than hit that constructor, as it will create appearance of working - like the situation you're in now.永远不想要那一击,事实上,程序在调试中崩溃比击中构造函数要好得多,因为它会产生工作的外观- 就像你现在所处的情况一样。

The reason your code "didn't do anything different" when you added the services.AddSingleton<HttpClient>(new HttpClient());添加services.AddSingleton<HttpClient>(new HttpClient());时代码“没有做任何不同”的原因code is because of your empty constructor - since the Logger service was still not configured, DI framework couldn't match the correct constructor - so instead of getting a meaningful error, the empty constructor ran (since it always matches) - causing debugging pain and suffering .代码是因为您的空构造函数- 由于仍未配置Logger服务,DI 框架无法匹配正确的构造函数 - 因此空构造函数运行(因为它总是匹配)而不是得到有意义的错误 - 导致调试痛苦和苦难

As an aside, I recommend reading up on how DI works underneath (maybe even build out your own DI container, a very simple one, for practice. Do not use your own DI container in production.), This is a good article: by the guy that practically invented this stuff: https://martinfowler.com/articles/injection.html顺便说一句,我建议阅读 DI 如何在下面工作(甚至可以构建自己的 DI 容器,一个非常简单的容器,用于练习。不要在生产中使用自己的 DI 容器。),这是一篇好文章:by实际上发明了这些东西的人: https://martinfowler.com/articles/injection.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM