在 .NET Core 中使用 IOptions<> 进行集成测试

Integration test with IOptions<> in .NET Core

我将 IOption<T> 传递给 CommandBus,这样我就可以从 ServiceBusSetting class 中获取设置。我想对我的总线进行集成测试。我不想解决它只是使用 new QueueCommandBus 并且需要将 IOptions 传递给它。

var services = new ServiceCollection().AddOptions();
        services.Configure<ServiceBusAppSettings>(Configuration.GetSection("ServiceBus"));
        var options = services.BuildServiceProvider().GetService<IOptions<ServiceBusAppSettings>>();

        ////Act
        var commandBus = new QueueCommandBus(options);

这工作正常,但在我的测试项目中从我的 appsetting.json 获取 IOptions<T> 感觉代码非常复杂。

知道这是唯一的方法还是有更好的方法?

您不需要创建 ServiceCollectionIServiceProviderIConfiguration 接口有一个 Bind() 方法,或者从 .NET Core 1.1 开始,Get<T> 可以用来直接获取 strongly-typed 对象:

var config = Configuration.GetSection("ServiceBus");

// .NET Core 1.0
var options = new ServiceBusAppSettings();
config.Bind(options);

// .NET Core 1.1
var options = config.Get<ServiceBusAppSettings>();

我喜欢将这些作为静态方法添加到我的 AppSettings strongly-typed 对象中,以便在我的网络应用程序和单元测试中从 JSON 加载它们很方便。

AppSettings.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;

namespace My.Namespace
{
    public class AppSettings
    {
        public class ServiceBusAppSettings
        {
            public string Setting1;
            public int Setting2;
        }

        public class ApiSettings
        {
            public bool FormatJson { get; set; }
        }

        public class MySqlSettings
        {
            public string User { get; set; }
            public string Password { get; set; }
            public string Host { get; set; }
            public string Database { get; set; }
            public int Port { get; set; } = 3306;

            public string GetConnectionString()
            {
                return $"Server={Host};Database={Database};Port={Port};Uid={User};Pwd={Password}";
            }

        }

        public ServiceBusAppSettings ServiceBus { get; set; } = new ServiceBusAppSettings();
        public ApiSettings Api { get; set; } = new ApiSettings();
        public MySqlSettings MySql { get; set; } = new MySqlSettings();

        // Static load helper methods. These could also be moved to a factory class.
        public static IConfigurationRoot GetConfiguration(string dir)
        {
            return GetConfiguration(dir, null);
        }

        public static IConfigurationRoot GetConfiguration(string dir, string environmentName)
        {
            if (string.IsNullOrEmpty(environmentName))
                environmentName = "Development";

            var builder = new ConfigurationBuilder()
                .SetBasePath(dir)
                .AddJsonFile("appsettings.json", true, true)
                .AddJsonFile($"appsettings.{environmentName}.json", true)
                .AddEnvironmentVariables();

            return builder.Build();
        }

        public static AppSettings GetSettings(string dir)
        {
            return GetSettings(dir, null);
        }

        public static AppSettings GetSettings(string dir, string environmentName)
        {
            var config = GetConfiguration(dir, environmentName);
            return GetSettings(config);
        }

        public static AppSettings GetSettings(IConfiguration config)
        {
            return config.Get<AppSettings>();
        }
    }
}

ASP.NET Core Startup.cs:(获取 strongly-typed 设置对象在配置其他服务的这个阶段通常很有帮助。 ..)

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        Configuration = AppSettings.GetConfiguration(env.ContentRootPath, env.EnvironmentName);
    }

    public IConfigurationRoot Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        // Configure the service collection.
        services.AddOptions();
        services.Configure<AppSettings>(Configuration);

        // It can also be handy to get the AppSettings object here.
        var settings = AppSettings.GetSettings(Configuration);

        // Add framework services.
        services.AddMvc()
            .AddJsonOptions(options =>
            {
                options.SerializerSettings.ContractResolver = new DefaultContractResolver();
                // Pretty-print JSON in Development
                options.SerializerSettings.Formatting = settings.Api.FormatJson ? Formatting.Indented : Formatting.None;
            });

        // Store DB connection info in AppSettings too...
        var conn = settings.MySql.GetConnectionString();
        services.AddDbContext<MyDbContext>(opt => opt.UseMySql(conn));
    }
}

测试中Class:

var testDir = AppContext.BaseDirectory;
var settings = AppSettings.GetSettings(testDir, "Test");

//Act
var commandBus = new QueueCommandBus(settings);