直接读取appsettings.json,或从Extension方法访问IOptions <t>

时间:2018-02-20 11:37:58

标签: unit-testing asp.net-core dependency-injection .net-core

我有一个扩展方法,用于从当前ClaimsPrincipal读取特定声明。但我还需要根据appsettings.json中的项目列表检查此值。 我通过使用ConfigurationBuilder()直接读取appsettings并使用与启动相同的方式来完成此工作,但不是使用

.SetBasePath(Directory.GetCurrentDirectory())
和我在创业公司一样,我正在使用

.SetBasePath(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location))

虽然不漂亮,但效果很好。 但是,当运行单元测试时,以下任何一个都不能让我到达appsettings

的位置
Directory.GetCurrentDirectory()
Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)

我无法看到将IHostingEnvironment或类似内容添加到扩展方法中以便读出appsettings,或者确实放弃ConfigurationBuilder()并获取{{1}的方法在扩展方法中,以单元测试和正在运行的代码正常工作的方式。

我认为必须有办法做到这一点?虽然我希望我根本不应该完全尝试并将检查项目列表完全提升到另一个类......

1 个答案:

答案 0 :(得分:3)

不建议将可能需要依赖的业务逻辑放入静态方法中。这使得很难将依赖项注入其中。选项很少:

  1. 将静态方法重新设计为服务,以便可以通过构造函数注入依赖项。的(推荐)
  2. public class Foo : IFoo
    {
        private readonly IOptions<FooOptions> optionsAccessor;
        public Foo(IOptions<FooOptions> optionsAccessor)
        {
            this.optionsAccessor = optionsAccessor ??
                throw new ArgumentNullException(nameof(optionsAccessor));
        }
    
        public void DoSomething()
        {
             var x = this.optionsAccessor;
    
             // Same implementation as your static method
        }
    }
    
    1. 将依赖项注入扩展方法的参数。
    2. public static void DoSomething(this object o, IOptions<FooOptions> optionsAccessor)
      {
          // Implementation
      }
      
      1. 将静态方法重新设计为抽象工厂like this example的外观。