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

Jno*_*men 9 asp.net-mvc integration-testing asp.net-core

我传给IOption<T>了我,CommandBus所以我可以从ServiceBusSetting班上得到设置.我想对我的总线进行集成测试.我不想解决它只是使用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);
Run Code Online (Sandbox Code Playgroud)

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

任何线索,如果这是唯一的方式或有更好的方法?

Tob*_*s J 8

您不需要创建ServiceCollectionIServiceProvider.该IConfiguration接口有一个Bind()方法,或者从.NET 1.1的核心以后,Get<T>你可以用它来直接获得强类型的对象:

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>();
Run Code Online (Sandbox Code Playgroud)

我喜欢将这些作为静态方法添加到我的AppSettings强类型对象中,以方便在我的Web应用程序和单元测试中从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>();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

ASP.NET Core Startup.cs:(在配置其他服务的过程中,获取强类型设置对象通常很有用......)

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));
    }
}
Run Code Online (Sandbox Code Playgroud)

在测试类中:

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

//Act
var commandBus = new QueueCommandBus(settings);
Run Code Online (Sandbox Code Playgroud)