【问题标题】:Getting IConfiguration in own ServiceCollection在自己的 ServiceCollection 中获取 IConfiguration
【发布时间】:2021-11-01 14:54:05
【问题描述】:

我正在向我的tests 发送fixture

在我的FixtureFactory 中,我正在制作我自己的ServiceCollection

    private static ServiceCollection CreateServiceCollection()
    {
        var services = new ServiceCollection();

        services.AddScoped<IConfiguration>();
        services.AddScoped<ITokenService, TokenService>();
        services.AddDbContext<TaskManagerDbContext>(o => o.UseInMemoryDatabase(Guid.NewGuid().ToString()));
        services.AddIdentity<ApplicationUser, IdentityRole>(options =>
        {
            options.Password.RequiredLength = 6;
            options.Password.RequireLowercase = false;
            options.Password.RequireUppercase = false;
            options.Password.RequireNonAlphanumeric = false;
            options.Password.RequireDigit = false;
            options.User.RequireUniqueEmail = true;
        }).AddEntityFrameworkStores<TaskManagerDbContext>();

        return services;
    }

然后,我从scope 得到这个services

    var services = CreateServiceCollection().BuildServiceProvider().CreateScope();

    var context = services.ServiceProvider.GetRequiredService<TaskManagerDbContext>();
    var userManager = services.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
    var roleManager = services.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
    var signInManager = services.ServiceProvider.GetRequiredService<SignInManager<ApplicationUser>>();
    var tokenService = services.ServiceProvider.GetRequiredService<TokenService>();

当我将TokenService 添加到我的ServiceCollection 时,问题就开始了。

TokenService 的构造函数如下所示:

    private readonly IConfiguration configuration;

    private readonly UserManager<ApplicationUser> userManager;

    public TokenService(IConfiguration configuration, UserManager<ApplicationUser> userManager)
    {
        this.configuration = configuration;
        this.userManager = userManager;
    }

当我启动我的Core 应用程序时它工作得很好,但不能从我上面提到的ServiceCollection 工作。

在测试中,我开始收到此错误:

消息:System.AggregateException:发生一个或多个错误。 (无法为服务类型“Microsoft.Extensions.Configuration.IConfiguration”实例化实现类型“Microsoft.Extensions.Configuration.IConfiguration”。)(以下构造函数参数没有匹配的夹具数据:ServicesFixture 夹具) ---- System.ArgumentException:无法为服务类型“Microsoft.Extensions.Configuration.IConfiguration”实例化实现类型“Microsoft.Extensions.Configuration.IConfiguration”。 ---- 以下构造函数参数没有匹配的夹具数据:ServicesFixture 夹具

当我将services.AddScoped&lt;IConfiguration&gt;(); 添加到我的ServiceCollection 以及当我开始获得所需的服务TokenService 时,此错误开始出现。

我的问题是,如何正确注册我在Service 中使用的Configuration

我正在使用Configurationsettings.json 获取项目。

编辑:

我的fixture 和示例测试类:

public class ServicesFixture
{
    public TaskManagerDbContext Context { get; private set; }

    public UserManager<ApplicationUser> UserManager { get; private set; }

    public RoleManager<IdentityRole> RoleManager { get; private set; }

    public SignInManager<ApplicationUser> SignInManager { get; private set; }

    public TokenService TokenService { get; private set; }

    public ServicesFixture()
    {
        var servicesModel = ServicesFactory.CreateProperServices();

        this.Context = servicesModel.Context;
        this.UserManager = servicesModel.UserManager;
        this.RoleManager = servicesModel.RoleManager;
        this.SignInManager = servicesModel.SignInManager;
        this.TokenService = servicesModel.TokenService;
    }

    [CollectionDefinition("ServicesTestCollection")]
    public class QueryCollection : ICollectionFixture<ServicesFixture>
    {
    }
}

测试:

[Collection("ServicesTestCollection")]
public class CreateProjectCommandTests
{
    private readonly TaskManagerDbContext context;

    public CreateProjectCommandTests(ServicesFixture fixture)
    {
        this.context = fixture.Context;
    }
}

EDIT2

当我从我的集合中删除 AddScoped&lt;IConfiguration&gt;(); 并运行测试时,我收到此错误:

消息:System.AggregateException:发生一个或多个错误。 (未注册类型“TaskManager.Infrastructure.Implementations.TokenService”的服务。)(以下构造函数参数没有匹配的夹具数据:ServicesFixture 夹具) ---- System.InvalidOperationException:没有注册类型“TaskManager.Infrastructure.Implementations.TokenService”的服务。 ---- 以下构造函数参数没有匹配的夹具数据:ServicesFixture 夹具

【问题讨论】:

  • 您添加了IConfiguration,但没有实现。
  • Startup.cs 配置刚刚注入。如何实现Configuration
  • 您也可以只为IConfiguration 创建一个Mock 并使用它。您实际上并不需要为单元测试创​​建 IServicesCollection
  • 我想使用我在WebApi 项目中使用的现有设置文件(在这种情况下,默认为appsettings.json
  • 或者无论如何,我可以制作另一个settings.json 文件并在我自己的ServiceCollection 中在我的Configuration 上实现它。 settings 文件不是问题 tbh

标签: c# asp.net-core dependency-injection .net-core asp.net-core-2.2


【解决方案1】:

您添加了IConfiguration,但没有实现。

startup.cs 中,框架会在幕后创建一个实现并添加它。您将必须使用ConfigurationBuilder 执行相同操作

var builder = new ConfigurationBuilder()
    //.SetBasePath("path here") //<--You would need to set the path
    .AddJsonFile("appsettings.json"); //or what ever file you have the settings

IConfiguration configuration = builder.Build();

services.AddScoped<IConfiguration>(_ => configuration);

//...

【讨论】:

  • 它工作正常!谢谢!你能告诉我,在测试环境中有什么更好的解决方案?从Api.csproj 获取settings 或在Tests.csproj 中创建另一个相同的settings 文件?
  • 有一个设置文件,让测试复制它用于测试。这样,对主要设置的任何更改都将根据需要进行测试。
  • 非常有帮助,我在我的一个类中调用它时遇到了类似的问题:var configuration = new ServiceCollection().BuildServiceProvider().GetService&lt;IConfiguration&gt;();,它在类的构造函数中返回null。我用你代码的前两部分替换了它,它工作正常。
猜你喜欢
  • 2018-01-26
  • 2022-10-07
  • 1970-01-01
  • 2020-08-27
  • 2018-06-09
  • 1970-01-01
  • 2015-11-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多