title: Populate IConfiguration for unit tests
body: <p>.NET Core configuration allows so many options to add values (environment variables, json files, command line args).</p>
  <p>I just can't figure out and find an answer how to populate it via code.</p>
  <p>I am writing unit tests for extension methods to configurations and I thought populating it in the unit tests via code would be easier than loading dedicated json files for each test.</p>
  <p>My current code:</p>
  <pre class="lang-cs prettyprint-override"><code>[Fact]
  public void Test_IsConfigured_Positive()
  {
  
    // test against this configuration
    IConfiguration config = new ConfigurationBuilder()
      // how to populate it via code
      .Build();
  
    // the extension method to test
    Assert.True(config.IsConfigured());
  
  }
  </code></pre>
  <p>Update:</p>
  <p>One special case is the &quot;empty section&quot; which would look like this in json.</p>
  <pre class="lang-json prettyprint-override"><code>{
    &quot;MySection&quot;: {
       // the existence of the section activates something triggering IsConfigured to be true but does not overwrite any default value
     }
   }
  </code></pre>
  <hr />
  <p>Update 2:</p>
  <p>As Matthew pointed out in the comments having an empty section in the json gives the same result as not having the section at all. I distilled an example and yes, that is the case. I was wrong expecting a different behaviour.</p>
  <p>So what do I do and what did I expect:</p>
  <p>I am writing unit tests for 2 extension methods for IConfiguration (actually because the binding of values in Get...Settings method does not work for some reason (but thats a different topic). They look like this:</p>
  <pre class="lang-cs prettyprint-override"><code>public static bool IsService1Configured(this IConfiguration configuration)
  {
    return configuration.GetSection(&quot;Service1&quot;).Exists();
  }
  
  public static MyService1Settings GetService1Settings(this IConfiguration configuration)
  {
    if (!configuration.IsService1Configured()) return null;
  
    MyService1Settings settings = new MyService1Settings();
    configuration.Bind(&quot;Service1&quot;, settings);
  
    return settings;
  }
  </code></pre>
  <p>My missunderstanding was that if I place an empty section in the appsettings the <code>IsService1Configured()</code> method would return <code>true</code> (which is obviously wrong now). The difference I expected is with having an empty section now the <code>GetService1Settings()</code> method returns <code>null</code> and not as I expected the <code>MyService1Settings</code> with all default values.</p>
  <p>Fortunately this still works for me since I won't have empty sections (or now know that I have to avoid those cases). It was just one theoretical case I came across while writing the unit tests.</p>
  <p>Further down the road (for those interested in).</p>
  <p>For what do I use it? Configuration based service activation/deactivation.</p>
  <p>I have an application which has a service / some services compiled into it. Depending on the deployment I need to activate/deactivate the services completly. This is because some (local or testings setups) do not have full  access to a complete infrastructure (helper services like caching, metrics...). And I do that via the appsettings. If the service is configured (the config section exists) it will be added. If the config section is not present it will not be used.</p>
  <hr />
  <p>The full code for the distilled example is below.</p>
  <ul>
  <li>in Visual Studio create a new API named WebApplication1 from the templates (without HTTPS and Authentication)</li>
  <li>delete the Startup class and appsettings.Development.json</li>
  <li>replace the code in Program.cs with the code below</li>
  <li>now in appsettings.json you can activate/deactivate the services by adding/removing <code>Service1</code> and <code>Service2</code> section</li>
  </ul>
  <pre class="lang-cs prettyprint-override"><code>using Microsoft.AspNetCore;
  using Microsoft.AspNetCore.Builder;
  using Microsoft.AspNetCore.Hosting;
  using Microsoft.AspNetCore.Mvc;
  using Microsoft.Extensions.Configuration;
  using Microsoft.Extensions.DependencyInjection;
  using Microsoft.Extensions.Logging;
  using Newtonsoft.Json;
  using System;
  
  namespace WebApplication1
  {
  
    public class MyService1Settings
    {
    public int? Value1 { get; set; }
    public int Value2 { get; set; }
    public int Value3 { get; set; } = -1;
    }
  
    public static class Service1Extensions
    {
  
    public static bool IsService1Configured(this IConfiguration configuration)
    {
    return configuration.GetSection(&quot;Service1&quot;).Exists();
    }
  
    public static MyService1Settings GetService1Settings(this IConfiguration configuration)
    {
    if (!configuration.IsService1Configured()) return null;
  
    MyService1Settings settings = new MyService1Settings();
    configuration.Bind(&quot;Service1&quot;, settings);
  
    return settings;
    }
  
    public static IServiceCollection AddService1(this IServiceCollection services, IConfiguration configuration, ILogger logger)
    {
  
    MyService1Settings settings = configuration.GetService1Settings();
  
    if (settings == null) throw new Exception(&quot;loaded MyService1Settings are null (did you forget to check IsConfigured in Startup.ConfigureServices?) &quot;);
  
    logger.LogAsJson(settings, &quot;MyServiceSettings1: &quot;);
  
    // do what ever needs to be done
  
    return services;
    }
  
    public static IApplicationBuilder UseService1(this IApplicationBuilder app, IConfiguration configuration, ILogger logger)
    {
  
    // do what ever needs to be done
  
    return app;
    }
  
    }
  
    public class Program
    {
  
      public static void Main(string[] args)
      {
        CreateWebHostBuilder(args).Build().Run();
      }
  
      public static IWebHostBuilder CreateWebHostBuilder(string[] args) =&gt;
        WebHost.CreateDefaultBuilder(args)
        .ConfigureLogging
          (
          builder =&gt; 
            {
              builder.AddDebug();
              builder.AddConsole();
            }
          )
        .UseStartup&lt;Startup&gt;();
        }
  
      public class Startup
      {
  
        public IConfiguration Configuration { get; }
        public ILogger&lt;Startup&gt; Logger { get; }
  
        public Startup(IConfiguration configuration, ILoggerFactory loggerFactory)
        {
        Configuration = configuration;
        Logger = loggerFactory.CreateLogger&lt;Startup&gt;();
        }
  
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
  
        // flavour 1: needs check(s) in Startup method(s) or will raise an exception
        if (Configuration.IsService1Configured()) {
        Logger.LogInformation(&quot;service 1 is activated and added&quot;);
        services.AddService1(Configuration, Logger);
        } else 
        Logger.LogInformation(&quot;service 1 is deactivated and not added&quot;);
  
        // flavour 2: checks are done in the extension methods and no Startup cluttering
        services.AddOptionalService2(Configuration, Logger);
  
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
      }
  
      // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
      public void Configure(IApplicationBuilder app, IHostingEnvironment env)
      {
  
        if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
  
        // flavour 1: needs check(s) in Startup method(s) or will raise an exception
        if (Configuration.IsService1Configured()) {
          Logger.LogInformation(&quot;service 1 is activated and used&quot;);
          app.UseService1(Configuration, Logger); }
        else
          Logger.LogInformation(&quot;service 1 is deactivated and not used&quot;);
  
        // flavour 2: checks are done in the extension methods and no Startup cluttering
        app.UseOptionalService2(Configuration, Logger);
  
        app.UseMvc();
      }
    }
  
    public class MyService2Settings
    {
      public int? Value1 { get; set; }
      public int Value2 { get; set; }
      public int Value3 { get; set; } = -1;
    }
  
    public static class Service2Extensions
    {
  
    public static bool IsService2Configured(this IConfiguration configuration)
    {
      return configuration.GetSection(&quot;Service2&quot;).Exists();
    }
  
    public static MyService2Settings GetService2Settings(this IConfiguration configuration)
    {
      if (!configuration.IsService2Configured()) return null;
  
      MyService2Settings settings = new MyService2Settings();
      configuration.Bind(&quot;Service2&quot;, settings);
  
      return settings;
    }
  
    public static IServiceCollection AddOptionalService2(this IServiceCollection services, IConfiguration configuration, ILogger logger)
    {
  
      if (!configuration.IsService2Configured())
      {
        logger.LogInformation(&quot;service 2 is deactivated and not added&quot;);
        return services;
      }
  
      logger.LogInformation(&quot;service 2 is activated and added&quot;);
  
      MyService2Settings settings = configuration.GetService2Settings();
      if (settings == null) throw new Exception(&quot;some settings loading bug occured&quot;);
  
      logger.LogAsJson(settings, &quot;MyService2Settings: &quot;);
      // do what ever needs to be done
      return services;
    }
  
    public static IApplicationBuilder UseOptionalService2(this IApplicationBuilder app, IConfiguration configuration, ILogger logger)
    {
  
      if (!configuration.IsService2Configured())
      {
        logger.LogInformation(&quot;service 2 is deactivated and not used&quot;);
        return app;
      }
  
      logger.LogInformation(&quot;service 2 is activated and used&quot;);
      // do what ever needs to be done
      return app;
    }
  }
  
    public static class LoggerExtensions
    {
      public static void LogAsJson(this ILogger logger, object obj, string prefix = null)
      {
        logger.LogInformation(prefix ?? string.Empty) + ((obj == null) ? &quot;null&quot; : JsonConvert.SerializeObject(obj, Formatting.Indented)));
      }
    }
  
  }
  </code></pre>